diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 977e28b041599064022f9d07a79ca3bd210ed754..5224e67cd8d52efe683e14375734aec560cf624a 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -3608,8 +3608,28 @@ namespace Common { switch (typetype) { case T_BOOL: case T_INT_A: - // TODO: add more types as they are implemented in - // the enc/decoding + case T_ENUM_A: + case T_BSTR_A: + case T_OSTR: + case T_REAL: + case T_NULL: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_BMPSTRING: + case T_UNIVERSALSTRING: + case T_UTF8STRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_GENERALSTRING: + case T_OID: + case T_ROID: + case T_SEQ_A: + case T_EMBEDDED_PDV: + case T_SEQOF: + case T_EXTERNAL: return true; default: return false; diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc index 5ed4470fea0ecf081a01abbe7452955c402c48d3..0bad3de588170cb3ed9ac552f680eab2c8c4bd79 100644 --- a/compiler2/Type_chk.cc +++ b/compiler2/Type_chk.cc @@ -2995,65 +2995,113 @@ void Type::chk_xer() { // XERSTUFF semantic check } void Type::chk_oer() { - //if (!is_asn1()) return; if (oerattrib == NULL) { oerattrib = new OerAST(); } - switch (typetype) { - case T_BOOL: - break; + Type* t = get_type_refd_last(); + switch (t->typetype) { case T_INT_A: { - if (is_constrained()) { - if (get_sub_type()->is_integer_subtype_notempty()) { - Location loc; - int_limit_t upper = get_sub_type()->get_int_limit(true, &loc); - int_limit_t lower = get_sub_type()->get_int_limit(false, &loc); - bool lower_inf = lower.get_type() != int_limit_t::NUMBER; - bool upper_inf = upper.get_type() != int_limit_t::NUMBER; - if (lower_inf || upper_inf) { - oerattrib->signed_ = lower_inf; - oerattrib->bytes = -1; + if (t->is_constrained() && t->get_sub_type()->is_subtype_notempty()) { + Location loc; + int_limit_t upper = t->get_sub_type()->get_int_limit(true, &loc); + int_limit_t lower = t->get_sub_type()->get_int_limit(false, &loc); + bool lower_inf = lower.get_type() != int_limit_t::NUMBER; + bool upper_inf = upper.get_type() != int_limit_t::NUMBER; + if (lower_inf || upper_inf) { + oerattrib->signed_ = lower_inf; + oerattrib->bytes = -1; + } else { + int_val_t low = lower.get_value(); + int_val_t up = upper.get_value(); + if (low < 0) { + oerattrib->signed_ = true; + if (low >= -128 && up <= 127) { + oerattrib->bytes = 1; + } else if (low >= -32768 && up <= 32767) { + oerattrib->bytes = 2; + } else if (low >= -2147483648LL && up <= 2147483647) { + oerattrib->bytes = 4; + } else if ((low+1) >= -9223372036854775807LL && up <= 9223372036854775807LL) { + oerattrib->bytes = 8; + } else { + oerattrib->bytes = -1; + } } else { - int_val_t low = lower.get_value(); - int_val_t up = upper.get_value(); - if (low < 0) { - oerattrib->signed_ = true; - if (low >= -128 && up <= 127) { - oerattrib->bytes = 1; - } else if (low >= -32768 && up <= 32767) { - oerattrib->bytes = 2; - } else if (low >= -2147483648LL && up <= 2147483647) { - oerattrib->bytes = 4; - } else if ((low+1) >= -9223372036854775807LL && up <= 9223372036854775807LL) { - oerattrib->bytes = 8; - } else { - oerattrib->bytes = -1; - } + static int_val_t uns_8_byte("18446744073709551615", NULL); + oerattrib->signed_ = false; + if (up <= 255) { + oerattrib->bytes = 1; + } else if (up <= 65535) { + oerattrib->bytes = 2; + } else if (up <= 4294967295LL) { + oerattrib->bytes = 4; + } else if (up <= uns_8_byte) { + oerattrib->bytes = 8; } else { - static int_val_t uns_8_byte("18446744073709551615", NULL); - oerattrib->signed_ = false; - if (up <= 255) { - oerattrib->bytes = 1; - } else if (up <= 65535) { - oerattrib->bytes = 2; - } else if (up <= 4294967295LL) { - oerattrib->bytes = 4; - } else if (up <= uns_8_byte) { - oerattrib->bytes = 8; - } else { - oerattrib->bytes = -1; - } + oerattrib->bytes = -1; } } - } else { - oerattrib->signed_ = true; - oerattrib->bytes = -1; } } else { oerattrib->signed_ = true; oerattrib->bytes = -1; } break; } + case T_BSTR_A: + case T_OSTR: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_BMPSTRING: + case T_UNIVERSALSTRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_GENERALSTRING: { + if (t->is_constrained() && t->get_sub_type()->is_subtype_notempty()) { + Location loc; + int_limit_t upper = t->get_sub_type()->get_int_limit(true, &loc); + int_limit_t lower = t->get_sub_type()->get_int_limit(false, &loc); + bool lower_inf = lower.get_type() != int_limit_t::NUMBER; + bool upper_inf = upper.get_type() != int_limit_t::NUMBER; + if (!lower_inf && !upper_inf) { + int_val_t low = lower.get_value(); + int_val_t up = upper.get_value(); + if (low == up) { + oerattrib->length = up.get_val(); + if (typetype == T_BMPSTRING) { + oerattrib->length *= 2; + } else if (typetype == T_UNIVERSALSTRING) { + oerattrib->length *= 4; + } + } + } + } + break; } + case T_SEQ_A: { + // extendable is always false. Probably a bug with is_extendable() + if (t->get_sub_type()) { + oerattrib->extendable = t->get_sub_type()->is_extendable(); + } + for (size_t i = 0; i < t->get_nof_comps(); i++) { + t->get_comp_byIndex(i)->get_type()->chk(); + } + break; } + case T_SEQOF: { + t->get_ofType()->chk(); + break; + } + case T_BOOL: + case T_ENUM_A: + case T_UTF8STRING: + case T_REAL: + case T_NULL: + case T_OID: + case T_ROID: + case T_EMBEDDED_PDV: + case T_EXTERNAL: + break; default: break; } diff --git a/compiler2/Type_codegen.cc b/compiler2/Type_codegen.cc index b4a443e5d52893d04b7b5240882aa055f3e657ca..ac2b27cb67362012c029ab46eabfbd3713cb2471 100644 --- a/compiler2/Type_codegen.cc +++ b/compiler2/Type_codegen.cc @@ -1087,14 +1087,16 @@ void Type::generate_code_oerdescriptor(output_struct *target) if (NULL == oerattrib) { target->source.global_vars = mputprintf(target->source.global_vars, - "const TTCN_OERdescriptor_t %s_oer_ = { -1, FALSE };\n" + "const TTCN_OERdescriptor_t %s_oer_ = { -1, FALSE, -1, FALSE };\n" , get_genname_own().c_str()); } else { target->source.global_vars = mputprintf(target->source.global_vars, - "const TTCN_OERdescriptor_t %s_oer_ = { %i, %s };\n" + "const TTCN_OERdescriptor_t %s_oer_ = { %i, %s, %i, %s };\n" , get_genname_own().c_str() , oerattrib->bytes - , oerattrib->signed_ ? "TRUE" : "FALSE"); + , oerattrib->signed_ ? "TRUE" : "FALSE" + , oerattrib->length + , oerattrib->extendable ? "TRUE" : "FALSE"); } } diff --git a/compiler2/encdec.c b/compiler2/encdec.c index 6cf924bfa75dc9f478af334527ad3bbd7c4278d5..a46403366449568a53f7368e79c79700c921b943 100644 --- a/compiler2/encdec.c +++ b/compiler2/encdec.c @@ -83,6 +83,11 @@ void def_encdec(const char *p_classname, "int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;\n" "int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);\n"); } + if(oer) { + def = mputprintf(def, + "int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const;\n" + "int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&);\n"); + } src=mputprintf(src, "void %s::encode(const TTCN_Typedescriptor_t& p_td," @@ -143,6 +148,14 @@ void def_encdec(const char *p_classname, " JSON_encode(p_td, tok);\n" " p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());\n" " break;}\n" + " case TTCN_EncDec::CT_OER: {\n" + " TTCN_EncDec_ErrorContext ec(" + "\"While OER-encoding type '%%s': \", p_td.name);\n" + " if(!p_td.oer)\n" + " TTCN_EncDec_ErrorContext::error_internal\n" + " (\"No OER descriptor available for type '%%s'.\", p_td.name);\n" + " OER_encode(p_td, p_buf);\n" + " break;}\n" " default:\n" " TTCN_error(\"Unknown coding method requested to encode" " type '%%s'\", p_td.name);\n" @@ -248,6 +261,15 @@ void def_encdec(const char *p_classname, " message was received\", p_td.name);\n" " p_buf.set_pos(tok.get_buf_pos());\n" " break;}\n" + " case TTCN_EncDec::CT_OER: {\n" + " TTCN_EncDec_ErrorContext ec(\"While OER-decoding type '%%s': \"," + " p_td.name);\n" + " if(!p_td.oer)\n" + " TTCN_EncDec_ErrorContext::error_internal\n" + " (\"No OER descriptor available for type '%%s'.\", p_td.name);\n" + " OER_struct p_oer;\n" + " OER_decode(p_td, p_buf, p_oer);\n" + " break;}\n" " default:\n" " TTCN_error(\"Unknown coding method requested to decode" " type '%%s'\", p_td.name);\n" diff --git a/compiler2/enum.c b/compiler2/enum.c index ac4e280cd5618d6c135aab884d2d8c3a7d7427ab..1eabf5a5b9cca516719ed04221e7dc798d311814 100644 --- a/compiler2/enum.c +++ b/compiler2/enum.c @@ -869,6 +869,63 @@ void defEnumClass(const enum_def *edef, output_struct *output) "}\n\n" , name, unknown_value, enum_type, unbound_value, unbound_value); } + + if (oer_needed) { + // OER encode + src = mputprintf(src, + "int %s::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const\n" + "{\n" + " if (enum_value == %s) {\n" + " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" + " \"Encoding an unbound value of enumerated type %s.\");\n" + " return -1;\n" + " }\n\n" + " if (enum_value >= 0 && enum_value < 128) {\n" + " char c = enum_value;\n" + " p_buf.put_c(c);\n" + " p_buf.increase_pos(1);\n" + " } else {\n" + // This case is the same as encoding a not restricted integer except + // the first bit is set to 1 before decoding + " INTEGER intval(enum_value);\n" + " TTCN_Buffer buf;\n" + " intval.OER_encode(INTEGER_descr_, buf);\n" + " unsigned char* uc = const_cast<unsigned char*>(buf.get_data());\n" + " *uc |= 1 << 7;\n" + " p_buf.put_buf(buf);\n" + " }\n" + " return 0;\n" + "}\n\n" + , name, unbound_value, dispname); + + // OER decode + src = mputprintf(src, + "int %s::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" + "{\n" + " const unsigned char* uc = p_buf.get_read_data();\n" + " if (!(uc[0] & 0x80)) {\n" + " if (is_valid_enum(uc[0])) {" + " enum_value = static_cast<%s>(uc[0]);\n" + " } else {\n" + " enum_value = %s;\n" + " }\n" + " } else {\n" + // This case is the same as decoding a not restricted integer except + // the first bit is set to 0 + " unsigned char* uc2 = const_cast<unsigned char*>(p_buf.get_read_data());\n" + " uc2[0] &= ~0x80;\n" + " INTEGER intval;\n" + " intval.OER_decode(INTEGER_descr_, p_buf, p_oer);\n" + " if (is_valid_enum(intval.get_val().get_val())) {\n" + " enum_value = static_cast<%s>(intval.get_val().get_val());\n" + " } else {\n" + " enum_value = %s;\n" + " }\n" + " }\n" + " return 0;\n" + "}\n\n" + , name, enum_type, unknown_value, enum_type, unknown_value); + } /* end of class */ def = mputstr(def, "};\n\n"); diff --git a/compiler2/record.c b/compiler2/record.c index 3c82e6eb469c77ea6bc56ae35fd8afcc3f9d5dcd..d15ddc1002aea46190e1df7969c9886031a0e9f4 100644 --- a/compiler2/record.c +++ b/compiler2/record.c @@ -4652,6 +4652,142 @@ void defRecordClass1(const struct_def *sdef, output_struct *output) src = mputstr(src, "}\n\n"); } + if (oer_needed) { + // OER encode, RT1 + src = mputprintf(src, + "int %s::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const\n" + "{\n" + " if (!is_bound()) {\n" + " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" + " \"Encoding an unbound %s value.\");\n" + " return -1;\n" + " }\n", name, sdef->kind == SET ? "set" : "record"); + size_t opt_elements = 0; + for (i = 0; i < sdef->nElements; i++) { + if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) { + opt_elements++; + } + } + int needed_bytes = opt_elements / 8 + 1; + + if (opt_elements != 0) { + src = mputprintf(src, + " unsigned char c[%i] = {0};\n" + , needed_bytes); + } + int ind = 0; + int pos = 8; + for (i = 0; i < sdef->nElements; i++) { + if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) { + pos--; + src = mputprintf(src, + " if (field_%s.is_present()) {\n" + " c[%i] += 1 << %i;\n" + " }\n" + , sdef->elements[i].name, ind, pos); + if (pos == 0) { + pos = 8; + ind++; + } + } + } + if (opt_elements != 0) { + src = mputprintf(src, + " p_buf.put_s(%i, c);\n" + , needed_bytes); + } + for (i = 0; i < sdef->nElements; i++) { + if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) { + src = mputprintf(src, + " if (field_%s.is_present())\n " + , sdef->elements[i].name); + } + src = mputprintf(src, + " field_%s.OER_encode(%s_descr_, p_buf);\n" + , sdef->elements[i].name, sdef->elements[i].typedescrname); + } + src = mputstr(src, + " return 0;\n" + "}\n\n"); + + // OER decode, RT1 + src = mputprintf(src, + "int %s::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" + "{\n", name); + if (opt_elements != 0) { + src = mputprintf(src, + " const unsigned char* uc = p_buf.get_read_data();\n" + " p_buf.increase_pos(%i);\n" + , needed_bytes); + } + ind = 0; + pos = 8; + for (i = 0; i < sdef->nElements; i++) { + if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) { + pos--; + src = mputprintf(src, + " if (uc[%i] & (1 << %i))\n" + " field_%s.OER_decode(%s_descr_, p_buf, p_oer);\n" + , ind, pos, sdef->elements[i].name + , sdef->elements[i].typedescrname); + if (sdef->elements[i].isOptional) { + src = mputprintf(src, " else\n" + " field_%s = OMIT_VALUE;\n" + , sdef->elements[i].name); + } + if (pos == 0) { + ind++; + pos = 8; + } + } else { + src = mputprintf(src, + " field_%s.OER_decode(%s_descr_, p_buf, p_oer);\n" + , sdef->elements[i].name + , sdef->elements[i].typedescrname); + } + } + if (sdef->has_opentypes) { + src = mputstr(src, + " TTCN_EncDec_ErrorContext ec_1(\"While decoding opentypes: \");" + " TTCN_Type_list p_typelist;\n" + " OER_decode_opentypes(p_typelist, p_buf, p_oer);\n"); + } + src = mputstr(src, + " return 0;\n" + "}\n\n"); + } + + if(sdef->has_opentypes) { + /* OER_decode_opentypes() */ + def=mputstr + (def, + "void OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer);\n"); + src=mputprintf + (src, + "void %s::OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" + "{\n" + " p_typelist.push(this);\n" + " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" + " TTCN_EncDec_ErrorContext ec_1;\n" + , name + ); + for(i=0; i<sdef->nElements; i++) { + src=mputprintf + (src, + " ec_1.set_msg(\"%s': \");\n" + " field_%s.OER_decode_opentypes(p_typelist, p_buf, p_oer);\n" + , sdef->elements[i].dispname + , sdef->elements[i].name + ); + } /* for i */ + src=mputstr + (src, + " p_typelist.pop();\n" + "}\n" + "\n" + ); + } /* if sdef->has_opentypes */ + /* end of class definition */ def = mputstr(def, "};\n\n"); @@ -6183,6 +6319,30 @@ static void defEmptyRecordClass(const struct_def *sdef, "}\n\n" , name); } + + if (oer_needed) { + // OER encode, RT1 + src = mputprintf(src, + "int %s::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const\n" + "{\n" + " if (!is_bound()) {\n" + " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" + " \"Encoding an unbound value of type %s.\");\n" + " return -1;\n" + " }\n\n" + " return 0;\n" + "}\n\n" + , name, dispname); + + // OER decode, RT1 + src = mputprintf(src, + "int %s::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&)\n" + "{\n" + " bound_flag = TRUE;\n" + " return 0;\n" + "}\n\n" + , name); + } /* closing class definition */ def = mputstr(def, "};\n\n"); diff --git a/compiler2/record_of.c b/compiler2/record_of.c index 2979cb8dff8f3aa09a1f84192e8e56a5798f5f48..ef490901aab14ad0757dde353be68906d1cd6fa7 100644 --- a/compiler2/record_of.c +++ b/compiler2/record_of.c @@ -1637,6 +1637,61 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "}\n\n" , name, type, type, type); } + if (oer_needed) { + // OER encode, RT1 + src = mputprintf(src, + "int %s::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const\n" + "{\n" + " if (!is_bound()) {\n" + " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" + " \"Encoding an unbound value of type %s.\");\n" + " return -1;\n" + " }\n\n" + " encode_oer_length(val_ptr->n_elements, p_buf, TRUE);\n" + " for (int i = 0; i < val_ptr->n_elements; ++i) {\n" + " (*this)[i].OER_encode(*p_td.oftype_descr, p_buf);\n" + " }\n" + " return 0;\n" + "}\n\n" + , name, dispname); + + // OER decode, RT1 + src = mputprintf(src, + "int %s::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" + "{\n" + " size_t nof_elem = decode_oer_length(p_buf, TRUE);\n" + " set_size(nof_elem);\n" + " for (size_t i = 0; i < nof_elem; i++) {\n" + " (*this)[i].OER_decode(*p_td.oftype_descr, p_buf, p_oer);\n" + " }\n" + " return 0;\n" + "}\n\n" + , name); + + if(sdef->has_opentypes) { + /* OER_decode_opentypes() */ + def=mputstr + (def, + "void OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer);\n"); + src=mputprintf + (src, + "void %s::OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" + "{\n" + " p_typelist.push(this);\n" + " TTCN_EncDec_ErrorContext ec_0(\"Component #\");\n" + " TTCN_EncDec_ErrorContext ec_1;\n" + " for(int elem_i=0; elem_i<n_elements; elem_i++) {\n" + " ec_1.set_msg(\"%%d: \", elem_i);\n" + " value_elements[elem_i].OER_decode_opentypes(p_typelist," + " p_buf, p_oer);\n" + " }\n" + " p_typelist.pop();\n" + "}\n" + "\n" + , name + ); + } + } /* end of class */ def = mputstr(def, "};\n\n"); @@ -3088,6 +3143,61 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct "}\n\n" , name, type); } + if (oer_needed) { + // OER encode, RT1, mem. alloc. optimised + src = mputprintf(src, + "int %s::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const\n" + "{\n" + " if (!is_bound()) {\n" + " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" + " \"Encoding an unbound value of type %s.\");\n" + " return -1;\n" + " }\n\n" + " encode_oer_length(n_elements, p_buf, TRUE);\n" + " for (int i = 0; i < n_elements; ++i) {\n" + " value_elements[i].OER_encode(*p_td.oftype_descr, p_buf);\n" + " }\n" + " return 0;\n" + "}\n\n" + , name, dispname); + + // OER decode, RT1, mem. alloc. optimised + src = mputprintf(src, + "int %s::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" + "{\n" + " size_t nof_elem = decode_oer_length(p_buf, TRUE);\n" + " set_size(nof_elem);\n" + " for (size_t i = 0; i < nof_elem; i++) {\n" + " (*this)[i].OER_decode(*p_td.oftype_descr, p_buf, p_oer);\n" + " }\n" + " return 0;\n" + "}\n\n" + , name); + + if(sdef->has_opentypes) { + /* OER_decode_opentypes() */ + def=mputstr + (def, + "void OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer);\n"); + src=mputprintf + (src, + "void %s::OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" + "{\n" + " p_typelist.push(this);\n" + " TTCN_EncDec_ErrorContext ec_0(\"Component #\");\n" + " TTCN_EncDec_ErrorContext ec_1;\n" + " for(int elem_i=0; elem_i<n_elements; elem_i++) {\n" + " ec_1.set_msg(\"%%d: \", elem_i);\n" + " value_elements[elem_i].OER_decode_opentypes(p_typelist," + " p_buf, p_oer);\n" + " }\n" + " p_typelist.pop();\n" + "}\n" + "\n" + , name + ); + } + } /* end of class */ def = mputstr(def, "};\n\n"); diff --git a/compiler2/subtype.hh b/compiler2/subtype.hh index 37d259193d508b1b84a5ac588262c5cfd8fd0394..a18ed840aa7b2541eb5a0c1ad7b6521e2cd083fe 100644 --- a/compiler2/subtype.hh +++ b/compiler2/subtype.hh @@ -218,8 +218,19 @@ public: bool is_length_compatible(const SubtypeConstraint *p_st) const; bool is_upper_limit_infinity() const; bool is_lower_limit_infinity() const; - bool is_integer_subtype_notempty() const - { return subtype==ST_INTEGER && integer_st && !integer_st->is_empty(); } + bool is_subtype_notempty() const + { size_limit_t sl; + return (subtype==ST_INTEGER && integer_st && !integer_st->is_empty()) || + (subtype==ST_BITSTRING && bitstring_st && !bitstring_st->is_empty()) || + (subtype==ST_HEXSTRING && hexstring_st && !hexstring_st->is_empty()) || + (subtype==ST_OCTETSTRING && octetstring_st && !octetstring_st->is_empty()) || + (subtype==ST_CHARSTRING && charstring_st && + charstring_st->get_size_limit(false, sl) == TTRUE && + charstring_st->get_size_limit(true, sl) == TTRUE) || + (subtype==ST_UNIVERSAL_CHARSTRING && universal_charstring_st && + universal_charstring_st->get_size_limit(false, sl) == TTRUE && + universal_charstring_st->get_size_limit(true, sl) == TTRUE); + } }; /** diff --git a/compiler2/ttcn3/OerAST.cc b/compiler2/ttcn3/OerAST.cc index d9c3d2c332cea5160ba802454b903ef7c99a56aa..a4a754150c1b9d096655d4a59219d72fd2a7171e 100644 --- a/compiler2/ttcn3/OerAST.cc +++ b/compiler2/ttcn3/OerAST.cc @@ -12,10 +12,13 @@ #include "OerAST.hh" OerAST::OerAST() : - bytes(0), - signed_(false) + bytes(-1), + signed_(false), + length(-1), + extendable(false) {} bool OerAST::empty() const { - return bytes == 0 && signed_ == false; + return bytes == -1 && signed_ == false && length == -1 && + extendable == false; } diff --git a/compiler2/ttcn3/OerAST.hh b/compiler2/ttcn3/OerAST.hh index 97bc58c55c5190ac15aad173fd7fc23b7b5e18dd..eb047006fb8429fdad40358af1543f13ab8240fa 100644 --- a/compiler2/ttcn3/OerAST.hh +++ b/compiler2/ttcn3/OerAST.hh @@ -16,6 +16,8 @@ class OerAST { public: int bytes; bool signed_; + int length; + bool extendable; OerAST(); bool empty() const; diff --git a/compiler2/union.c b/compiler2/union.c index a61dec8f90223d10fe39fe39ec637f2838f3ee2a..831af099abf18bdd3bd49eda075f191e832c6397 100644 --- a/compiler2/union.c +++ b/compiler2/union.c @@ -2368,6 +2368,191 @@ void defUnionClass(struct_def const *sdef, output_struct *output) } } + if (oer_needed) { + // OER encode + src = mputprintf(src, + "int %s::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const\n" + "{\n", name); + src = mputstr(src, " switch(union_selection) {\n"); + for (i = 0; i < sdef->nElements; ++i) { + src = mputprintf(src, " case %s_%s:\n", selection_prefix, sdef->elements[i].name); + if (sdef->has_opentypes == FALSE) { + src = mputprintf(src, + " encode_oer_tag(*%s_descr_.ber, p_buf);\n" + " field_%s->OER_encode(%s_descr_, p_buf);\n" + " break;\n" + , sdef->elements[i].typedescrname, sdef->elements[i].name, sdef->elements[i].typedescrname); + } else { + src = mputprintf(src, + " {\n" + " TTCN_Buffer buf;\n" + " field_%s->OER_encode(%s_descr_, buf);\n" + " encode_oer_length(buf.get_len(), p_buf, FALSE);\n" + " p_buf.put_buf(buf);\n" + " break; }\n" + , sdef->elements[i].name, sdef->elements[i].typedescrname); + } + } + src = mputprintf(src, + " default:\n" + " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, \n" + " \"Encoding an unbound value of type %s.\");\n" + " return -1;\n" + " }\n\n" + , dispname); + src = mputstr(src, + " return 0;\n" + "}\n"); + + if (use_runtime_2) { + // OER encode for negative testing + def = mputstr(def, + "int OER_encode_negtest(const Erroneous_descriptor_t*, " + "const TTCN_Typedescriptor_t&, TTCN_Buffer&) const;\n"); + //todo + } + // OER decode + src = mputprintf(src, + "int %s::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" + "{\n", name); + if (sdef->ot == NULL) { + src = mputstr(src, + " const ASN_Tag_t& descr = decode_oer_tag(p_buf);\n"); + for (i = 0; i < sdef->nElements; ++i) { + src = mputprintf(src, + " if (%s_descr_.ber->tags[%s_descr_.ber->n_tags-1].tagclass == descr.tagclass &&\n" + " %s_descr_.ber->tags[%s_descr_.ber->n_tags-1].tagnumber == descr.tagnumber) {\n" + " %s%s().OER_decode(%s_descr_, p_buf, p_oer);\n" + " } else \n" + , sdef->elements[i].typedescrname, sdef->elements[i].typedescrname, sdef->elements[i].typedescrname + , sdef->elements[i].typedescrname, at_field, sdef->elements[i].name, sdef->elements[i].typedescrname); + } + src = mputprintf(src, + "{\n" + " TTCN_error(\"Cannot find matching tag for type %s\");\n" + "}\n", name); + } else { + src = mputstr(src, + " size_t pos = decode_oer_length(p_buf, FALSE);\n" + " size_t prev_pos = p_buf.get_pos();\n" + " p_buf.increase_pos(pos);\n" + " p_oer.opentype_poses.push_back(prev_pos);\n" + ); + } + src = mputstr(src, " return 0;\n}\n"); + + if (sdef->ot || sdef->has_opentypes) { /* theoretically, these are + mutually exlusive */ + /* OER_decode_opentypes() */ + def = mputstr(def, "void OER_decode_opentypes(" + "TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer);\n"); + src = mputprintf(src, "void %s::OER_decode_opentypes(" + "TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" + "{\n", name); + if (sdef->ot) { + AtNotationList_t *anl = &sdef->ot->anl; + OpentypeAlternativeList_t *oal = &sdef->ot->oal; + src = mputprintf(src, + " if (union_selection != %s) return;\n" + " TTCN_EncDec_ErrorContext ec_0(\"While decoding open type '%s': " + "\");\n", unbound_value, dispname); + if (oal->nElements > 0) { + size_t oal_i, anl_i; + char *s2; + /* variable declarations - the referenced components */ + for (anl_i = 0; anl_i < anl->nElements; anl_i++) { + AtNotation_t *an = anl->elements + anl_i; + src = mputprintf(src, " const %s& f_%lu = static_cast<const %s*>" + "(p_typelist.get_nth(%lu))->%s;\n", an->type_name, + (unsigned long) (anl_i + 1), an->parent_typename, + (unsigned long) an->parent_level, an->sourcecode); + } /* for anl_i */ + src = mputstr(src, " {\n" + " TTCN_EncDec_ErrorContext ec_1(\"Alternative '\");\n" + " TTCN_EncDec_ErrorContext ec_2;\n"); + s2 = mprintf("%*s", (int)(anl->nElements + 2) * 2, ""); + for (oal_i = 0; oal_i < oal->nElements; oal_i++) { + size_t if_level; + OpentypeAlternative_t *oa = oal->elements + oal_i; + if (oal_i > 0) { + for (if_level = 0; if_level < anl->nElements; if_level++) + if (oa->const_valuenames[if_level]) break; + for (i = anl->nElements; i > if_level; i--) + src = mputprintf(src, "%*s}\n", (int)(i + 1) * 2, ""); + } /* if oal_i */ + else if_level = 0; + for (anl_i = if_level; anl_i < anl->nElements; anl_i++) { + src = mputprintf(src, "%*s%sif (f_%lu == %s) {\n", + (int)(anl_i + 2) * 2, "", + oal_i && anl_i <= if_level ? "else " : "", + (unsigned long) (anl_i + 1), oa->const_valuenames[anl_i]); + } /* for anl_i */ + src = mputprintf(src, "%sunion_selection = %s_%s;\n" + "%sfield_%s = new %s;\n" + "%sec_2.set_msg(\"%s': \");\n" + "size_t pos = p_buf.get_pos();\n" + "p_buf.set_pos(p_oer.opentype_poses.at(0));\n" + "p_oer.opentype_poses.erase_at(0);\n" + "OER_struct tmp_oer;\n" + "%sfield_%s->OER_decode(%s_descr_, p_buf, tmp_oer);\n" + "p_buf.set_pos(pos);\n", + s2, selection_prefix, oa->alt, s2, oa->alt, oa->alt_typename, s2, + oa->alt_dispname, s2, oa->alt, oa->alt_typedescrname); + } /* for oal_i */ + Free(s2); + if (oal->nElements > 0) + for (i = anl->nElements; i > 0; i--) + src = mputprintf(src, "%*s}\n", (int)(i+1)*2, ""); + src = mputprintf(src, " }\n" + " if (union_selection == %s) {\n" + " ec_0.error(TTCN_EncDec::ET_DEC_OPENTYPE, \"Cannot decode " + "open type: broken component relation constraint.\");\n" + " if (TTCN_EncDec::get_error_behavior(" + "TTCN_EncDec::ET_DEC_OPENTYPE) != TTCN_EncDec::EB_IGNORE) {\n" + " TTCN_Logger::log_str(TTCN_WARNING, \"The value%s of" + " constraining component%s:\");\n", unbound_value, + anl->nElements > 1 ? "s" : "", anl->nElements > 1 ? "s" : ""); + for (anl_i = 0; anl_i < anl->nElements; anl_i++) { + AtNotation_t *an = anl->elements + anl_i; + src = mputprintf(src, + " TTCN_Logger::begin_event(TTCN_WARNING);\n" + " TTCN_Logger::log_event_str(\"Component '%s': \");\n" + " f_%lu.log();\n" + " TTCN_Logger::end_event();\n", an->dispname, + (unsigned long) (anl_i + 1)); + } /* for anl_i */ + src = mputstr(src, " }\n" + " }\n"); + } /* if oal->nElements>0 */ + else { + src = mputstr(src, " ec_0.error(TTCN_EncDec::ET_DEC_OPENTYPE, " + "\"Cannot decode open type: the constraining object set is " + "empty.\");\n"); + } /* oal->nElements==0 */ + } /* if sdef->ot */ + else { /* if !sdef->ot (but has_opentypes) */ + src = mputstr(src, + " p_typelist.push(this);\n" + " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n" + " TTCN_EncDec_ErrorContext ec_1;\n" + " switch (union_selection) {\n"); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, " case %s_%s:\n" + " ec_1.set_msg(\"%s': \");\n" + " field_%s->OER_decode_opentypes(p_typelist, p_buf, p_oer);\n" + " break;\n", selection_prefix, sdef->elements[i].name, + sdef->elements[i].dispname, sdef->elements[i].name); + } /* for i */ + src = mputstr(src, " default:\n" + " break;\n" + " }\n" + " p_typelist.pop();\n"); + } /* if has opentypes */ + src = mputstr(src, "}\n" + "\n"); + } /* if sdef->ot || sdef->has_opentypes */ + } + /* end of class definition */ def = mputstr(def, "};\n\n"); diff --git a/core/ASN_EmbeddedPDV.cc b/core/ASN_EmbeddedPDV.cc index e5bb066adb6ba234a8868428cb4524cee3163714..7e262a7dbc2b865db32800446d255374a214b788 100644 --- a/core/ASN_EmbeddedPDV.cc +++ b/core/ASN_EmbeddedPDV.cc @@ -30,6 +30,7 @@ #include "ASN_EmbeddedPDV.hh" #include "../common/dbgnew.hh" +#include "OER.hh" /* @@ -881,6 +882,68 @@ int EMBEDDED_PDV_identification::XER_decode(const XERdescriptor_t& p_td, return 1; } +int EMBEDDED_PDV_identification::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + switch (union_selection) { + case ALT_syntaxes: + p_buf.put_c(128); // tag + field_syntaxes->OER_encode(p_td, p_buf); + break; + case ALT_syntax: + p_buf.put_c(129); + field_syntax->OER_encode(OBJID_descr_, p_buf); + break; + case ALT_presentation__context__id: + p_buf.put_c(130); + field_presentation__context__id->OER_encode(INTEGER_descr_, p_buf); + break; + case ALT_context__negotiation: + p_buf.put_c(131); + field_context__negotiation->OER_encode(p_td, p_buf); + break; + case ALT_transfer__syntax: + p_buf.put_c(132); + field_transfer__syntax->OER_encode(OBJID_descr_, p_buf); + break; + case ALT_fixed: + p_buf.put_c(133); + field_fixed->OER_encode(p_td, p_buf); + break; + default: + TTCN_EncDec_ErrorContext::error_internal("Unknown selection."); + break; + } + return 0; +} + +int EMBEDDED_PDV_identification::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer) { + const unsigned char* uc = p_buf.get_read_data(); + p_buf.increase_pos(1); + switch (uc[0]) { + case 128: + syntaxes().OER_decode(p_td, p_buf, p_oer); + break; + case 129: + syntax().OER_decode(OBJID_descr_, p_buf, p_oer); + break; + case 130: + presentation__context__id().OER_decode(INTEGER_descr_, p_buf, p_oer); + break; + case 131: + context__negotiation().OER_decode(p_td, p_buf, p_oer); + break; + case 132: + transfer__syntax().OER_decode(OBJID_descr_, p_buf, p_oer); + break; + case 133: + fixed().OER_decode(p_td, p_buf, p_oer); + break; + default: + TTCN_EncDec_ErrorContext::error_internal("Unknown selection."); + break; + } + return 0; +} + /******************** EMBEDDED_PDV_identification_template ********************/ void EMBEDDED_PDV_identification_template::clean_up() @@ -1827,6 +1890,18 @@ int EMBEDDED_PDV_identification_syntaxes::XER_decode(const XERdescriptor_t& /*p_ return 0; // TODO maybe return proper value } +int EMBEDDED_PDV_identification_syntaxes::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const { + field_abstract.OER_encode(OBJID_descr_, p_buf); + field_transfer.OER_encode(OBJID_descr_, p_buf); + return 0; +} + +int EMBEDDED_PDV_identification_syntaxes::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer) { + field_abstract.OER_decode(OBJID_descr_, p_buf, p_oer); + field_transfer.OER_decode(OBJID_descr_, p_buf, p_oer); + return 0; +} + /******************** EMBEDDED_PDV_identification_syntaxes_template ********************/ struct EMBEDDED_PDV_identification_syntaxes_template::single_value_struct { @@ -2571,6 +2646,18 @@ int EMBEDDED_PDV_identification_context__negotiation::XER_decode( return 0; // TODO sensible return value } +int EMBEDDED_PDV_identification_context__negotiation::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const { + field_presentation__context__id.OER_encode(INTEGER_descr_, p_buf); + field_transfer__syntax .OER_encode(OBJID_descr_, p_buf); + return 0; +} + +int EMBEDDED_PDV_identification_context__negotiation::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer) { + field_presentation__context__id.OER_decode(INTEGER_descr_, p_buf, p_oer); + field_transfer__syntax .OER_decode(OBJID_descr_, p_buf, p_oer); + return 0; +} + struct EMBEDDED_PDV_identification_context__negotiation_template::single_value_struct { INTEGER_template field_presentation__context__id; OBJID_template field_transfer__syntax; @@ -3273,6 +3360,12 @@ void EMBEDDED_PDV::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec_ErrorContext::error_internal ("No JSON descriptor available for type '%s'.", p_td.name); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); } @@ -3321,6 +3414,13 @@ void EMBEDDED_PDV::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec_ErrorContext::error_internal ("No JSON descriptor available for type '%s'.", p_td.name); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); } @@ -3445,6 +3545,23 @@ int EMBEDDED_PDV::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, return 1; } +int EMBEDDED_PDV::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + if(!is_bound()) { + TTCN_EncDec_ErrorContext::error + (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value."); + } + field_identification.OER_encode(p_td, p_buf); + encode_oer_length(field_data__value.lengthof(), p_buf, FALSE); + p_buf.put_os(field_data__value); + return 0; +} + +int EMBEDDED_PDV::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer) { + field_identification.OER_decode(p_td, p_buf, p_oer); + field_data__value.OER_decode(OCTETSTRING_descr_, p_buf, p_oer); + return 0; +} + struct EMBEDDED_PDV_template::single_value_struct { EMBEDDED_PDV_identification_template field_identification; UNIVERSAL_CHARSTRING_template field_data__value__descriptor; diff --git a/core/ASN_EmbeddedPDV.hh b/core/ASN_EmbeddedPDV.hh index 456ff2c860a2cbec2d4e8898a112efb2c9f21133..1e2ead679a95d464892aacba4502476ff5cfcc07 100644 --- a/core/ASN_EmbeddedPDV.hh +++ b/core/ASN_EmbeddedPDV.hh @@ -102,6 +102,8 @@ public: TTCN_Buffer& p_buf, unsigned int flavor, unsigned int flavor2, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t*); + int OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer&) const; + int OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer&, OER_struct&); private: boolean BER_decode_set_selection(const ASN_BER_TLV_t& p_tlv); public: @@ -224,6 +226,8 @@ public: boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, unsigned int, int, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int, unsigned int, embed_values_dec_struct_t*); + int OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer&) const; + int OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer&, OER_struct&); }; class EMBEDDED_PDV_identification_syntaxes_template : public Base_Template { @@ -331,6 +335,8 @@ public: boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, unsigned int, int, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int, unsigned int, embed_values_dec_struct_t*); + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); }; class EMBEDDED_PDV_identification_context__negotiation_template : public Base_Template { @@ -444,6 +450,8 @@ public: boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, unsigned int, int, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t&, XmlReaderWrap&, unsigned int, unsigned int, embed_values_dec_struct_t*); + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); }; class EMBEDDED_PDV_template : public Base_Template { diff --git a/core/ASN_External.cc b/core/ASN_External.cc index be83c7c082badb1682c29bcf4daeff52d0f712ee..abe554dba9b2234dc1464d3122fdcd10774c73bb 100644 --- a/core/ASN_External.cc +++ b/core/ASN_External.cc @@ -40,6 +40,7 @@ #include "Addfunc.hh" #include "../common/dbgnew.hh" +#include "OER.hh" /* * This type is used to BER encode/decode the EXTERNAL type. @@ -120,6 +121,8 @@ namespace { /* anonymous namespace */ TTCN_Buffer& p_buf, unsigned int flavor, unsigned int flavor2, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t*); + int OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const; + int OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer); private: boolean BER_decode_set_selection(const ASN_BER_TLV_t& p_tlv); public: @@ -178,6 +181,8 @@ namespace { /* anonymous namespace */ TTCN_Buffer& p_buf, unsigned int flavor, unsigned int flavor2, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t*); + int OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const; + int OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer); }; /** Transform the information from the visible format to the encoding format @@ -505,6 +510,48 @@ namespace { /* anonymous namespace */ bail: return 0; // FIXME return value } + + int EXTERNALtransfer_encoding::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const { + switch (union_selection) { + case ALT_single__ASN1__type: + encode_oer_tag(*EXTERNALtransfer_encoding_single__ASN1__type_descr_.ber, p_buf); + field_single__ASN1__type->OER_encode(BITSTRING_descr_, p_buf); + break; + case ALT_octet__aligned: + encode_oer_tag(*EXTERNALtransfer_encoding_octet__aligned_descr_.ber, p_buf); + field_octet__aligned ->OER_encode(OCTETSTRING_descr_, p_buf); + break; + case ALT_arbitrary: + field_arbitrary ->OER_encode(BITSTRING_descr_, p_buf); + break; + case UNBOUND_VALUE: + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound value"); + break; + default: + TTCN_EncDec_ErrorContext::error_internal("Unknown selection."); + // TODO something at all ? + break; + } + return 0; + } + + int EXTERNALtransfer_encoding::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer) { + const ASN_Tag_t& tag = decode_oer_tag(p_buf); + if (tag.tagclass == EXTERNALtransfer_encoding_single__ASN1__type_ber_.tags[0].tagclass && + tag.tagnumber == EXTERNALtransfer_encoding_single__ASN1__type_ber_.tags[0].tagnumber) { + single__ASN1__type().OER_decode(BITSTRING_descr_, p_buf, p_oer); + } else if (tag.tagclass == EXTERNALtransfer_encoding_octet__aligned_ber_.tags[0].tagclass && + tag.tagnumber == EXTERNALtransfer_encoding_octet__aligned_ber_.tags[0].tagnumber) { + octet__aligned().OER_decode(OCTETSTRING_descr_, p_buf, p_oer); + } else if (tag.tagclass == EXTERNALtransfer_encoding_arbitrary_ber_.tags[0].tagclass && + tag.tagnumber == EXTERNALtransfer_encoding_arbitrary_ber_.tags[0].tagnumber) { + arbitrary().OER_decode(BITSTRING_descr_, p_buf, p_oer); + } else { + TTCN_EncDec_ErrorContext::error_internal("Unknown selection."); + } + return 0; + } /******************** EXTERNALtransfer class ********************/ @@ -630,6 +677,48 @@ namespace { /* anonymous namespace */ } return 1; // decode successful } + + int EXTERNALtransfer::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + char c = 0; + if (field_direct__reference.is_present()) { + c += 1 << 7; + } + if (field_indirect__reference.is_present()) { + c += 1 << 6; + } + if (field_data__value__descriptor.is_present()) { + c += 1 << 5; + } + p_buf.put_c(c); + field_direct__reference .OER_encode(OBJID_descr_, p_buf); + field_indirect__reference .OER_encode(INTEGER_descr_, p_buf); + field_data__value__descriptor.OER_encode(ObjectDescriptor_descr_, p_buf); + field_encoding .OER_encode(p_td, p_buf); + return 0; + } + + int EXTERNALtransfer::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer) { + const unsigned char* uc = p_buf.get_read_data(); + p_buf.increase_pos(1); + if ((uc[0] >> 7) & 1) { + field_direct__reference.OER_decode(OBJID_descr_, p_buf, p_oer); + } else { + field_direct__reference = OMIT_VALUE; + } + if ((uc[0] >> 6) & 1) { + field_indirect__reference.OER_decode(INTEGER_descr_, p_buf, p_oer); + } else { + field_indirect__reference = OMIT_VALUE; + } + if ((uc[0] >> 5) & 1) { + field_data__value__descriptor.OER_decode(ObjectDescriptor_descr_, p_buf, p_oer); + } else { + field_data__value__descriptor = OMIT_VALUE; + } + field_encoding.OER_decode(OCTETSTRING_descr_, p_buf, p_oer); + return 0; + } + } // end of anonymous namespace /* @@ -736,6 +825,24 @@ int EXTERNAL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, return 1; // decode successful } +int EXTERNAL::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + if(!is_bound()) { + TTCN_EncDec_ErrorContext::error + (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value."); + } + EXTERNALtransfer xfer; + xfer.load(*this); + return xfer.OER_encode(p_td, p_buf); + return 0; +} + +int EXTERNAL::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer) { + EXTERNALtransfer xfer; + xfer.OER_decode(p_td, p_buf, p_oer); + transfer(&xfer); + return 0; +} + /* generated stuff */ void EXTERNAL_identification::clean_up() @@ -3468,6 +3575,12 @@ void EXTERNAL::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTC TTCN_EncDec_ErrorContext::error_internal ("No JSON descriptor available for type '%s'.", p_td.name); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); } @@ -3516,6 +3629,13 @@ void EXTERNAL::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTC TTCN_EncDec_ErrorContext::error_internal ("No JSON descriptor available for type '%s'.", p_td.name); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); } diff --git a/core/ASN_External.hh b/core/ASN_External.hh index 6542606b81ad1dfca7bd11904e342688bd5d24f1..37d05732c38ec6c591a36543ab15e7eb7efdd4fd 100644 --- a/core/ASN_External.hh +++ b/core/ASN_External.hh @@ -29,6 +29,7 @@ #include "Objid.hh" #include "Octetstring.hh" #include "Universal_charstring.hh" +#include "TEXT.hh" class EXTERNAL_identification; class EXTERNAL_identification_template; @@ -425,6 +426,8 @@ public: TTCN_Buffer& p_buf, unsigned int flavor, unsigned int flavor2, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t*); + int OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const; + int OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer); }; class EXTERNAL_template : public Base_Template { diff --git a/core/ASN_Null.cc b/core/ASN_Null.cc index 831638a96b66e2900f81428fb8cc5950e7921510..62b334d63538d356247a31c9d4c04bab20aa63fb 100644 --- a/core/ASN_Null.cc +++ b/core/ASN_Null.cc @@ -29,6 +29,7 @@ #include "Logger.hh" #include "Encdec.hh" #include "BER.hh" +#include "OER.hh" #include "../common/dbgnew.hh" @@ -147,6 +148,12 @@ void ASN_NULL::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} case TTCN_EncDec::CT_RAW: default: TTCN_error("Unknown coding method requested to encode type '%s'", @@ -196,6 +203,13 @@ void ASN_NULL::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, , p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} case TTCN_EncDec::CT_RAW: default: TTCN_error("Unknown coding method requested to decode type '%s'", @@ -319,6 +333,20 @@ int ASN_NULL::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, b return (int)dec_len; } +int ASN_NULL::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound ASN.1 NULL value."); + return -1; + } + return 0; +} + +int ASN_NULL::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&) { + bound_flag = TRUE; + return 0; +} + boolean operator==(asn_null_type, const ASN_NULL& other_value) { if (!other_value.is_bound()) TTCN_error("The right operand of comparison " diff --git a/core/ASN_Null.hh b/core/ASN_Null.hh index 733dbd2c760237a14b17f6088176f2e3e0c43673..3f68f318081251be78d633b5f7eac1c9c9e5fae2 100644 --- a/core/ASN_Null.hh +++ b/core/ASN_Null.hh @@ -94,6 +94,14 @@ public: /** Decodes accordingly to the JSON decoding rules. * Returns the length of the encoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + + /** Encodes accordingly to the OER encoding rules. + * Returns the length of the encoded data. */ + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Decodes accordingly to the OER decoding rules. + * Returns the length of the encoded data. */ + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); }; extern boolean operator==(asn_null_type par_value, const ASN_NULL& other_value); diff --git a/core/Basetype.cc b/core/Basetype.cc index 936015d3cae01a8f1cc918d527c27809fca817e6..342983d2570a61762ed0ed6008786208f2b92efa 100644 --- a/core/Basetype.cc +++ b/core/Basetype.cc @@ -192,7 +192,8 @@ void Base_Type::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( "No OER descriptor available for type '%s'.", p_td.name); - OER_decode(p_td, p_buf); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", @@ -1039,7 +1040,7 @@ int Base_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer&) const return 0; } -int Base_Type::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer&) +int Base_Type::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer&, OER_struct&) { TTCN_error("OER decoding requested for type '%s' which has no" " OER decoding method.", p_td.name); @@ -1140,25 +1141,25 @@ const TTCN_Typedescriptor_t BOOLEAN_descr_={"BOOLEAN", &BOOLEAN_ber_, &BOOLEAN_raw_, &BOOLEAN_text_, &BOOLEAN_xer_, &BOOLEAN_json_, &BOOLEAN_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t INTEGER_descr_={"INTEGER", &INTEGER_ber_, - &INTEGER_raw_, &INTEGER_text_, &INTEGER_xer_, &INTEGER_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + &INTEGER_raw_, &INTEGER_text_, &INTEGER_xer_, &INTEGER_json_, &INTEGER_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t FLOAT_descr_={"REAL", &FLOAT_ber_, &FLOAT_raw_, - NULL, &FLOAT_xer_, &FLOAT_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + NULL, &FLOAT_xer_, &FLOAT_json_, &FLOAT_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t VERDICTTYPE_descr_={"verdicttype", NULL, NULL, NULL, &VERDICTTYPE_xer_, &VERDICTTYPE_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t OBJID_descr_={"OBJECT IDENTIFIER", &OBJID_ber_, - NULL, NULL, &OBJID_xer_, &OBJID_json_, NULL, NULL, TTCN_Typedescriptor_t::OBJID}; + NULL, NULL, &OBJID_xer_, &OBJID_json_, &OBJID_oer_, NULL, TTCN_Typedescriptor_t::OBJID}; const TTCN_Typedescriptor_t BITSTRING_descr_={"BIT STRING", &BITSTRING_ber_, - &BITSTRING_raw_, NULL, &BITSTRING_xer_, &BITSTRING_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + &BITSTRING_raw_, NULL, &BITSTRING_xer_, &BITSTRING_json_, &BITSTRING_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t HEXSTRING_descr_={"hexstring", NULL, &HEXSTRING_raw_, NULL, &HEXSTRING_xer_, &HEXSTRING_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t OCTETSTRING_descr_={"OCTET STRING", - &OCTETSTRING_ber_, &OCTETSTRING_raw_, &OCTETSTRING_text_, &OCTETSTRING_xer_, &OCTETSTRING_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + &OCTETSTRING_ber_, &OCTETSTRING_raw_, &OCTETSTRING_text_, &OCTETSTRING_xer_, &OCTETSTRING_json_, &OCTETSTRING_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t CHARSTRING_descr_={"charstring", NULL, &CHARSTRING_raw_, &CHARSTRING_text_, &CHARSTRING_xer_, &CHARSTRING_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; @@ -1173,44 +1174,44 @@ const TTCN_Typedescriptor_t DEFAULT_descr_={"default", NULL, NULL, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t ASN_NULL_descr_={"NULL", &ASN_NULL_ber_, NULL, - NULL, &ASN_NULL_xer_, &ASN_NULL_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + NULL, &ASN_NULL_xer_, &ASN_NULL_json_, &ASN_NULL_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t ASN_ANY_descr_={"ANY", &ASN_ANY_ber_, NULL, NULL, NULL, &ASN_ANY_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t EXTERNAL_descr_={"EXTERNAL", &EXTERNAL_ber_, NULL, - NULL, &EXTERNAL_xer_, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + NULL, &EXTERNAL_xer_, NULL, &EXTERNAL_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t EMBEDDED_PDV_descr_={"EMBEDDED PDV", - &EMBEDDED_PDV_ber_, NULL, NULL, &EMBEDDED_PDV_xer_, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + &EMBEDDED_PDV_ber_, NULL, NULL, &EMBEDDED_PDV_xer_, NULL, &EMBEDDED_PDV_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t CHARACTER_STRING_descr_={"CHARACTER STRING", &CHARACTER_STRING_ber_, NULL, NULL, &CHARACTER_STRING_xer_, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t ObjectDescriptor_descr_={"ObjectDescriptor", - &ObjectDescriptor_ber_, NULL, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING}; + &ObjectDescriptor_ber_, NULL, NULL, NULL, NULL, &ObjectDescriptor_oer_, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING}; const TTCN_Typedescriptor_t UTF8String_descr_={"UTF8String", &UTF8String_ber_, - NULL, NULL, &UTF8String_xer_, &UTF8String_json_, NULL, NULL, TTCN_Typedescriptor_t::UTF8STRING}; + NULL, NULL, &UTF8String_xer_, &UTF8String_json_, &UTF8String_oer_, NULL, TTCN_Typedescriptor_t::UTF8STRING}; const TTCN_Typedescriptor_t ASN_ROID_descr_={"RELATIVE-OID", &ASN_ROID_ber_, - NULL, NULL, &ASN_ROID_xer_, &ASN_ROID_json_, NULL, NULL, TTCN_Typedescriptor_t::ROID}; + NULL, NULL, &ASN_ROID_xer_, &ASN_ROID_json_, &ASN_ROID_oer_, NULL, TTCN_Typedescriptor_t::ROID}; const TTCN_Typedescriptor_t NumericString_descr_={"NumericString", - &NumericString_ber_, NULL, NULL, &NumericString_xer_, &NumericString_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + &NumericString_ber_, NULL, NULL, &NumericString_xer_, &NumericString_json_, &NumericString_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t PrintableString_descr_={"PrintableString", - &PrintableString_ber_, NULL, NULL, &PrintableString_xer_, &PrintableString_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + &PrintableString_ber_, NULL, NULL, &PrintableString_xer_, &PrintableString_json_, &PrintableString_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t TeletexString_descr_={"TeletexString", - &TeletexString_ber_, NULL, NULL, &TeletexString_xer_, &TeletexString_json_, NULL, NULL, TTCN_Typedescriptor_t::TELETEXSTRING}; + &TeletexString_ber_, NULL, NULL, &TeletexString_xer_, &TeletexString_json_, &TeletexString_oer_, NULL, TTCN_Typedescriptor_t::TELETEXSTRING}; const TTCN_Typedescriptor_t& T61String_descr_=TeletexString_descr_; const TTCN_Typedescriptor_t VideotexString_descr_={"VideotexString", - &VideotexString_ber_, NULL, NULL, &VideotexString_xer_, &VideotexString_json_, NULL, NULL, TTCN_Typedescriptor_t::VIDEOTEXSTRING}; + &VideotexString_ber_, NULL, NULL, &VideotexString_xer_, &VideotexString_json_, &VideotexString_oer_, NULL, TTCN_Typedescriptor_t::VIDEOTEXSTRING}; const TTCN_Typedescriptor_t IA5String_descr_={"IA5String", &IA5String_ber_, - NULL, NULL, &IA5String_xer_, &IA5String_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + NULL, NULL, &IA5String_xer_, &IA5String_json_, &IA5String_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t ASN_GeneralizedTime_descr_={"GeneralizedTime", &ASN_GeneralizedTime_ber_, NULL, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; @@ -1219,19 +1220,19 @@ const TTCN_Typedescriptor_t ASN_UTCTime_descr_={"UTCTime", &ASN_UTCTime_ber_, NULL, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t GraphicString_descr_={"GraphicString", - &GraphicString_ber_, NULL, NULL, &GraphicString_xer_, &GraphicString_json_, NULL, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING}; + &GraphicString_ber_, NULL, NULL, &GraphicString_xer_, &GraphicString_json_, &GraphicString_oer_, NULL, TTCN_Typedescriptor_t::GRAPHICSTRING}; const TTCN_Typedescriptor_t VisibleString_descr_={"VisibleString", - &VisibleString_ber_, NULL, NULL, &VisibleString_xer_, &VisibleString_json_, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + &VisibleString_ber_, NULL, NULL, &VisibleString_xer_, &VisibleString_json_, &VisibleString_oer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t& ISO646String_descr_=VisibleString_descr_; const TTCN_Typedescriptor_t GeneralString_descr_={"GeneralString", - &GeneralString_ber_, NULL, NULL, &GeneralString_xer_, &GeneralString_json_, NULL, NULL, TTCN_Typedescriptor_t::GENERALSTRING}; + &GeneralString_ber_, NULL, NULL, &GeneralString_xer_, &GeneralString_json_, &GeneralString_oer_, NULL, TTCN_Typedescriptor_t::GENERALSTRING}; const TTCN_Typedescriptor_t UniversalString_descr_={"UniversalString", - &UniversalString_ber_, NULL, NULL, &UniversalString_xer_, &UniversalString_json_, NULL, NULL, TTCN_Typedescriptor_t::UNIVERSALSTRING}; + &UniversalString_ber_, NULL, NULL, &UniversalString_xer_, &UniversalString_json_, &UniversalString_oer_, NULL, TTCN_Typedescriptor_t::UNIVERSALSTRING}; const TTCN_Typedescriptor_t BMPString_descr_={"BMPString", &BMPString_ber_, - NULL, NULL, &BMPString_xer_, &BMPString_json_, NULL, NULL, TTCN_Typedescriptor_t::BMPSTRING}; + NULL, NULL, &BMPString_xer_, &BMPString_json_, &BMPString_oer_, NULL, TTCN_Typedescriptor_t::BMPSTRING}; diff --git a/core/Basetype.hh b/core/Basetype.hh index a79714098468db99f8659542ec865c6e9bf3e9d1..204027954bbe4d7163e3de87d4aee098987fd0be 100644 --- a/core/Basetype.hh +++ b/core/Basetype.hh @@ -49,6 +49,7 @@ class Module_Param; class Module_Param_Name; struct embed_values_enc_struct_t; struct embed_values_dec_struct_t; +struct OER_struct; /** @brief Type descriptor * @@ -396,6 +397,7 @@ public: virtual int encode_raw(TTCN_Buffer& p_buf) const; virtual int RAW_encode_negtest_raw(RAW_enc_tree& p_myleaf) const; virtual int JSON_encode_negtest_raw(JSON_Tokenizer&) const; + virtual int OER_encode_negtest_raw(JSON_Tokenizer&) const; //TODO #endif /** Examines whether this message corresponds the tags in the @@ -620,7 +622,21 @@ public: /** Decode OER. * @note Basetype::OER_decode throws an error. */ - VIRTUAL_IF_RUNTIME_2 int OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf); + VIRTUAL_IF_RUNTIME_2 int OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer); + + VIRTUAL_IF_RUNTIME_2 void OER_decode_opentypes( + TTCN_Type_list& /*p_typelist*/, TTCN_Buffer& /*p_buf*/, OER_struct& /*p_oer*/) {} + + #ifdef TITAN_RUNTIME_2 + /** Encode with OER encoding negative test. + * @return the length of the encoding + * @param p_err_descr erroneous type descriptor + * @param p_td type descriptor + * @param p_tok JSON tokenizer for the encoded data + * @note Basetype::JSON_encode_negtest throws an error. */ + virtual int OER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t& p_td, + TTCN_Buffer& p_buf) const; +#endif /** not a component by default (components will return true) */ inline boolean is_component() { return FALSE; } @@ -850,6 +866,22 @@ public: /** Decodes accordingly to the JSON encoding rules. * Returns the length of the decoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + + /** Encodes accordingly to the OER encoding rules. + * Returns the length of the encoded data. */ + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Negative testing for the OER encoder + * Encodes this value according to the OER encoding rules, but with the + * modifications (errors) specified in the erroneous descriptor parameter. */ + int OER_encode_negtest(const Erroneous_descriptor_t*, const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Decodes accordingly to the OER encoding rules. + * Returns the length of the decoded data. */ + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); + + virtual void OER_decode_opentypes( + TTCN_Type_list& /*p_typelist*/, TTCN_Buffer& /*p_buf*/, OER_struct& /*p_oer*/); /** @returns \c true if this is a set-of type, * \c false if this is a record-of type */ @@ -997,6 +1029,21 @@ public: /** Decodes accordingly to the JSON encoding rules. * Returns the length of the decoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + + /** Encodes accordingly to the JSON encoding rules. + * Returns the length of the encoded data. */ + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Negative testing for the OER encoder + * Encodes this value according to the OER encoding rules, but with the + * modifications (errors) specified in the erroneous descriptor parameter. */ + int OER_encode_negtest(const Erroneous_descriptor_t*, const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Decodes accordingly to the OER encoding rules. + * Returns the length of the decoded data. */ + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); + + virtual void OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer); void set_err_descr(Erroneous_descriptor_t* p_err_descr) { err_descr=p_err_descr; } Erroneous_descriptor_t* get_err_descr() const { return err_descr; } @@ -1061,6 +1108,14 @@ public: /** Decodes accordingly to the JSON encoding rules. * Returns the length of the decoded data. */ virtual int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + + /** Encodes accordingly to the OER encoding rules. + * Returns the length of the encoded data. */ + virtual int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Decodes accordingly to the OER encoding rules. + * Returns the length of the decoded data. */ + virtual int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); }; struct Enum_Type : public Base_Type { diff --git a/core/Bitstring.cc b/core/Bitstring.cc index 0c9d4b13e47ca2ced292547e17b2608b2d0544bc..219289b91bf063837c20f5addaa670565a9476b8 100644 --- a/core/Bitstring.cc +++ b/core/Bitstring.cc @@ -36,6 +36,7 @@ #include "Optional.hh" #include "../common/dbgnew.hh" +#include "OER.hh" // bitstring value class @@ -692,6 +693,12 @@ void BITSTRING::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); @@ -760,6 +767,13 @@ void BITSTRING::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, , p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); @@ -1265,6 +1279,65 @@ int BITSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_ return (int)dec_len; } +int BITSTRING::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound bitstring value."); + return -1; + } + if (p_td.oer->length == -1) { + size_t bytes = 1 + val_ptr->n_bits / 8; + int rem = (val_ptr->n_bits % 8); + if (rem != 0) { + bytes++; + } + encode_oer_length(bytes, p_buf, FALSE); + p_buf.put_c(rem == 0 ? 0 : 8 - rem); + } + char c = 0; + int pos = 8; + for (int i = 0; i < val_ptr->n_bits; i++) { + pos--; + c += get_bit(i) << pos; + if (pos == 0) { + p_buf.put_c(c); + c = 0; + pos = 8; + } + } + if (pos != 8) { + p_buf.put_c(c); + } + return 0; +} + +int BITSTRING::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct&) { + + size_t bytes; + if (p_td.oer->length == -1) { + bytes = decode_oer_length(p_buf, FALSE) - 1; + const unsigned char* uc = p_buf.get_read_data(); + init_struct((bytes * 8) - uc[0]); + p_buf.increase_pos(1); + } else { + bytes = p_td.oer->length / 8; + if (p_td.oer->length % 8 != 0) { + bytes++; + } + init_struct(p_td.oer->length); + } + + const unsigned char* uc = p_buf.get_read_data(); + int bit_pos = 0; + for (size_t i = 0; i < bytes; i++) { + for (int j = 7; j >= 0 && bit_pos < val_ptr->n_bits; j--) { + set_bit(bit_pos, (uc[i] & (1 << j))); + bit_pos++; + } + } + p_buf.increase_pos(bytes); + return 0; +} // bitstring element class diff --git a/core/Bitstring.hh b/core/Bitstring.hh index 1339c212cc0381232888bd190cbe8aa093a80277..6c5154703cb6a32c986ecb3ad5032a652a231c67 100644 --- a/core/Bitstring.hh +++ b/core/Bitstring.hh @@ -209,6 +209,14 @@ public: /** Decodes accordingly to the JSON decoding rules. * Returns the length of the encoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + + /** Encodes accordingly to the OER encoding rules. + * Returns the length of the encoded data. */ + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Decodes accordingly to the OER decoding rules. + * Returns the length of the encoded data. */ + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); }; class BITSTRING_ELEMENT { diff --git a/core/Boolean.cc b/core/Boolean.cc index 66c0114600cda5df6801a041486600207d034579..b870d3821830cd171996ce688274d9cb497399f1 100644 --- a/core/Boolean.cc +++ b/core/Boolean.cc @@ -33,6 +33,7 @@ #include "Encdec.hh" #include "RAW.hh" #include "BER.hh" +#include "OER.hh" #include "TEXT.hh" #include "Charstring.hh" #include "XmlReader.hh" @@ -344,7 +345,8 @@ void BOOLEAN::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( "No OER descriptor available for type '%s'.", p_td.name); - OER_decode(p_td, p_buf); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", @@ -805,7 +807,7 @@ int BOOLEAN::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const return 1; } -int BOOLEAN::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) +int BOOLEAN::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct&) { const unsigned char* c = p_buf.get_read_data(); p_buf.increase_pos(1); diff --git a/core/Boolean.hh b/core/Boolean.hh index 4bba9003fde414ed6c32d9c414a85ac1c2539b1c..d52476cfecccfee7fdad5d895e58a75116c55e54 100644 --- a/core/Boolean.hh +++ b/core/Boolean.hh @@ -137,7 +137,7 @@ public: /** Decodes accordingly to the OER encoding rules. * Returns the length of the decoded data. */ - int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf); + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct&); }; extern boolean operator&&(boolean bool_value, const BOOLEAN& other_value); diff --git a/core/Charstring.cc b/core/Charstring.cc index ed0a4a1534226bd302cc19df9098c9d954002751..dc09bdd58a37204f5a16e87157922e29376971c7 100644 --- a/core/Charstring.cc +++ b/core/Charstring.cc @@ -43,6 +43,7 @@ #include "Optional.hh" #include "../common/dbgnew.hh" +#include "OER.hh" #include <string.h> #include <ctype.h> @@ -840,6 +841,12 @@ void CHARSTRING::encode(const TTCN_Typedescriptor_t& p_td, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); @@ -927,6 +934,13 @@ void CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td, , p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); @@ -1813,6 +1827,35 @@ int CHARSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p return (int)dec_len; } +int CHARSTRING::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound charstring value."); + return -1; + } + + if (p_td.oer->length == -1) { + encode_oer_length(lengthof(), p_buf, FALSE); + } + p_buf.put_cs(*this); + return 0; +} + +int CHARSTRING::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct&) { + size_t bytes; + if (p_td.oer->length == -1) { + bytes = decode_oer_length(p_buf, FALSE); + } else { + bytes = p_td.oer->length; + } + const unsigned char* uc = p_buf.get_read_data(); + init_struct(bytes); + for (size_t i = 0; i < bytes; i++) { + val_ptr->chars_ptr[i] = uc[i]; + } + p_buf.increase_pos(bytes); + return 0; +} CHARSTRING_ELEMENT::CHARSTRING_ELEMENT(boolean par_bound_flag, CHARSTRING& par_str_val, int par_char_pos) diff --git a/core/Charstring.hh b/core/Charstring.hh index 29cc731113219fc350423d0a859bee3c50dfe177..114b804aa3a3e749f4578d0934bc052034d98f99 100644 --- a/core/Charstring.hh +++ b/core/Charstring.hh @@ -280,6 +280,10 @@ public: * Returns the length of the decoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); + #ifdef TITAN_RUNTIME_2 virtual int encode_raw(TTCN_Buffer& p_buf) const; /** Adds this charstring to the end of a JSON buffer as raw data. diff --git a/core/Float.cc b/core/Float.cc index 92aaa21e9c74051446731d4b7d2919efec18dc60..dacecc43719583ba2d84d2b9e0230fed26442db4 100644 --- a/core/Float.cc +++ b/core/Float.cc @@ -36,6 +36,7 @@ #include "Encdec.hh" #include "RAW.hh" #include "BER.hh" +#include "OER.hh" #include "Charstring.hh" #include "Addfunc.hh" #include "XmlReader.hh" @@ -364,6 +365,12 @@ void FLOAT::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); @@ -431,6 +438,13 @@ void FLOAT::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, , p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); @@ -1152,6 +1166,212 @@ int FLOAT::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, return (int)dec_len; } +int FLOAT::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound float value."); + return -1; + } + // Mostly copied from BER + if (float_value==0.0) { + p_buf.put_c(0); + } else if (float_value==(double)INFINITY) { + p_buf.put_c(1); + p_buf.put_c(64); + } else if (float_value==-(double)INFINITY) { + p_buf.put_c(1); + p_buf.put_c(65); + } else if (isnan((double)float_value)) { + p_buf.put_c(1); + p_buf.put_c(66); + } else { + double mantissa, exponent; + exponent=floor(log10(fabs(float_value)))+1.0-DBL_DIG; + mantissa=floor(float_value*pow(10.0,-exponent)+0.5); + if(mantissa)while(!fmod(mantissa,10.0))mantissa/=10.0,exponent+=1.0; + char * uc = + mprintf("\x03%.f.E%s%.0f", mantissa, exponent==0.0?"+":"", exponent); + size_t len = mstrlen(uc); + p_buf.put_c(len); + p_buf.put_s(len, (unsigned char*)uc); + Free(uc); + } + return 0; +} + +int FLOAT::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct&) { + TTCN_EncDec_ErrorContext ec("While decoding REAL type: "); + const unsigned char* uc = p_buf.get_read_data(); + const size_t bytes = uc[0]; + p_buf.increase_pos(1); + uc = p_buf.get_read_data(); + // Mostly copied from BER + if(bytes==0) { + float_value=0.0; + } + else if(uc[0] & 0x80) { + /* binary encoding */ + /** \todo Perhaps it were good to implement this. Perhaps not. :) */ + ec.warning("Sorry, decoding of binary encoded REAL values not" + " supported."); + float_value=0.0; + } + else if(uc[0] & 0x40) { + /* SpecialRealValue */ + if(bytes>1) + ec.error(TTCN_EncDec::ET_INVAL_MSG, + "In case of SpecialRealValue, the length of V-part must be 1" + " (See X.690 8.5.8)."); + if (uc[0] & 0x02) { + float_value=NOT_A_NUMBER; + } else if(uc[0] & 0x01) + /* MINUS-INFINITY */ + float_value=-INFINITY; + else { + /* PLUS-INFINITY */ + float_value=INFINITY; + } + } + else { + /* decimal encoding */ + if((uc[0] & 0x3C) || (uc[0] & 0x3F) == 0x00 ) + ec.error(TTCN_EncDec::ET_INVAL_MSG, + "This is a reserved value: 0x%x (See X.690 8.5.7).", + uc[0]); + int NR=uc[0] & 0x03; // which NumericalRepresentation + boolean + leadingzero=FALSE, + NR_error=FALSE; + const unsigned char + *Vstr_last=uc+bytes-1, + *sign=NULL, + *mant1=NULL, + *decmark=NULL, + *mant2=NULL, + *expmark=NULL, + *expsign=NULL, + *expo=NULL, + *ptr=uc+1; + size_t + mant1_len=0, + mant2_len=0, + expo_len=0; + long exponum; + if(bytes==1) goto dec_error; + while(*ptr==' ') { + if(ptr==Vstr_last) goto dec_error; + ptr++; + } + if(*ptr=='+' || *ptr=='-') { + sign=ptr; + if(ptr==Vstr_last) goto dec_error; + ptr++; + } + while(*ptr=='0') { + leadingzero=TRUE; + if(ptr==Vstr_last) goto str_end; + ptr++; + } + while(*ptr>='0' && *ptr<='9') { + if(mant1_len==0) mant1=ptr; + mant1_len++; + if(ptr==Vstr_last) goto str_end; + ptr++; + } + if(*ptr=='.' || *ptr==',') { + decmark=ptr; + if(ptr==Vstr_last) goto str_end; + ptr++; + } + while(*ptr>='0' && *ptr<='9') { + if(mant2_len==0) mant2=ptr; + mant2_len++; + if(ptr==Vstr_last) goto str_end; + ptr++; + } + if(!leadingzero && !mant1 && !mant2) goto dec_error; + if(*ptr=='e' || *ptr=='E') { + expmark=ptr; + if(ptr==Vstr_last) goto dec_error; + ptr++; + } + if(*ptr=='+' || *ptr=='-') { + expsign=ptr; + if(ptr==Vstr_last) goto dec_error; + ptr++; + } + while(*ptr=='0') { + expo=ptr; + if(ptr==Vstr_last) goto str_end; + ptr++; + } + while(*ptr>='0' && *ptr<='9') { + if(expo_len==0) expo=ptr; + expo_len++; + if(ptr==Vstr_last) goto str_end; + ptr++; + } + if(expo_len==0 && expo!=NULL) expo_len=1; /* only leading zero */ + if(expsign && !expo) goto dec_error; + ec.error(TTCN_EncDec::ET_INVAL_MSG, + "Superfluous part at the end of decimal encoding."); + str_end: + /* check NR */ + if(NR==1) { + if(decmark || expmark) NR_error=TRUE; + } + else if(NR==2) { + if(expmark) NR_error=TRUE; + } + if(NR_error) + ec.error(TTCN_EncDec::ET_INVAL_MSG, + "This decimal encoding does not conform to NR%d form.", NR); + while(mant2_len>1 && mant2[mant2_len-1]=='0') mant2_len--; + if(mant2_len==1 && *mant2=='0') mant2_len=0, mant2=NULL; + float_value=0.0; + if(mant1) for(size_t i=0; i<mant1_len; i++) { + float_value*=10.0; + float_value+=static_cast<double>(mant1[i]-'0'); + } // for i if... + if(mant2) for(size_t i=0; i<mant2_len; i++) { + float_value*=10.0; + float_value+=static_cast<double>(mant2[i]-'0'); + } // for i if... + exponum=0; + if(expo) { + if(ceil(log10(log10(DBL_MAX)))<expo_len) { + /* overflow */ + if(expsign && *expsign=='-') { + float_value=0.0; + } + else { + if(sign && *sign=='-') float_value=-INFINITY; + else float_value=INFINITY; + } + goto end; + } // overflow + else { + /* no overflow */ + for(size_t i=0; i<expo_len; i++) { + exponum*=10; + exponum+=static_cast<int>(expo[i]-'0'); + } // for i + if(expsign && *expsign=='-') + exponum*=-1; + } // no overflow + } // if expo + if(mant2) exponum-=mant2_len; + float_value*=pow(10.0, static_cast<double>(exponum)); + goto end; + dec_error: + ec.error(TTCN_EncDec::ET_INVAL_MSG, "Erroneous decimal encoding."); + float_value=0.0; + } + end: + p_buf.increase_pos(bytes); + bound_flag=TRUE; + return 0; +} // global functions diff --git a/core/Float.hh b/core/Float.hh index 83afeaed90095ce32cb612d34fe4984b038fdf0a..169946af78c2ae92eb60a6ad6b291edec04d6369 100644 --- a/core/Float.hh +++ b/core/Float.hh @@ -161,6 +161,14 @@ public: /** Decodes accordingly to the JSON encoding rules. * Returns the length of the decoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + + /** Encodes accordingly to the OER encoding rules. + * Returns the length of the encoded data. */ + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Decodes accordingly to the OER encoding rules. + * Returns the length of the decoded data. */ + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); }; extern double operator+(double double_value, const FLOAT& other_value); diff --git a/core/Integer.cc b/core/Integer.cc index e8fb9f33ef7328ff8262f989f1bb4c0861d2d20d..875bb09671103d065a5148a8137b1017c4157355 100644 --- a/core/Integer.cc +++ b/core/Integer.cc @@ -38,6 +38,7 @@ #include "RAW.hh" #include "BER.hh" #include "TEXT.hh" +#include "OER.hh" #include "Charstring.hh" #include "Addfunc.hh" #include "XmlReader.hh" @@ -894,7 +895,8 @@ void INTEGER::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( "No OER descriptor available for type '%s'.", p_td.name); - OER_decode(p_td, p_buf); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", @@ -1782,7 +1784,7 @@ int INTEGER::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) c "Encoding an unbound integer value."); return -1; } - + // Most of the encoding is copied from the integer BER encoding. if (native_flag) { RInt value = val.native; @@ -1827,7 +1829,6 @@ int INTEGER::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) c unsigned char* bn_as_bin = (unsigned char*) Malloc(num_bytes); BN_bn2bin(D, bn_as_bin); - boolean pad = FALSE; if (BN_is_negative(D)) { for(size_t i = 0; i < num_bytes; ++i){ bn_as_bin[i] = ~bn_as_bin[i]; @@ -1846,37 +1847,15 @@ int INTEGER::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) c } } } - pad = !(bn_as_bin[0] & 0x80); - } else { - pad = bn_as_bin[0] & 0x80; } if (p_td.oer->bytes == -1) { - if (num_bytes < 128) { - p_buf.put_c(num_bytes); - } else { - size_t bytes = num_bytes; - TTCN_Buffer buff; - // Encode length in maybe more than 1 bytes - size_t needed_bytes = 0; - while (bytes != 0) { - bytes >>= 8; - needed_bytes++; - } - for (int i = needed_bytes - 1; i >= 0; i--) { - buff.put_c(static_cast<unsigned char>(num_bytes >> i*8)); - } - char c = 0; - c |= 1 << 7; - c+= needed_bytes; - p_buf.put_c(c); - p_buf.put_buf(buff); - } + encode_oer_length(num_bytes, p_buf, FALSE); } else { int rem_bytes = p_td.oer->bytes - num_bytes; - char c = BN_is_negative(D) ? 0xFF : 0; + char pad = BN_is_negative(D) ? 0xFF : 0; for (int i = 0; i < rem_bytes; i++) { - p_buf.put_c(c); + p_buf.put_c(pad); } } p_buf.put_s(num_bytes, bn_as_bin); @@ -1885,30 +1864,17 @@ int INTEGER::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) c return 0; } -int INTEGER::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) +int INTEGER::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct&) { // Most of the decoding is copied from the integer BER decoding. size_t num_bytes = 0; // Get the number of bytes that the integer is encoded on if (p_td.oer->bytes == -1) { - const unsigned char* uc = p_buf.get_read_data(); - p_buf.increase_pos(1); - // First bit is 1, its length is encoded in subsequent bytes - if (*uc & 0x80) { - size_t bytes = *uc & 0x7F; - for (size_t i = 1; i < bytes+1; i++) { - num_bytes += uc[i] << (bytes-i)*8; - } - p_buf.increase_pos(bytes); - } else { - // its length is encoded in the last 7 bytes - num_bytes = *uc & 0x7F; - } + num_bytes = decode_oer_length(p_buf, FALSE); } else { num_bytes = p_td.oer->bytes; } - const unsigned char* const ucstr = p_buf.get_read_data(); if ((num_bytes > sizeof(RInt)) || (num_bytes >= 4 && p_td.oer->signed_ == FALSE)) { // Bignum const boolean negative = ucstr[0] & 0x80 && (p_td.oer->signed_ == TRUE || p_td.oer->bytes == -1); diff --git a/core/Integer.hh b/core/Integer.hh index 53289394ecb6f911edb92a0189084518319c257c..a538db16f53b7065729dbbf9c2282aec7e0f0821 100644 --- a/core/Integer.hh +++ b/core/Integer.hh @@ -199,7 +199,7 @@ public: /** Decodes accordingly to the OER encoding rules. * Returns the length of the decoded data. */ - int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf); + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer); }; extern INTEGER operator+(int int_value, const INTEGER& other_value); diff --git a/core/OER.cc b/core/OER.cc index 238b762df4ed88ef5e4fd273f589056bda0bd50d..927ef94c56ffbc7757ba68152ab3f99b8bc7191b 100644 --- a/core/OER.cc +++ b/core/OER.cc @@ -11,5 +11,194 @@ * ******************************************************************************/ #include "OER.hh" +#include "Encdec.hh" +#include "BER.hh" +#include "../common/memory.h" +#include "Error.hh" -const TTCN_OERdescriptor_t BOOLEAN_oer_ = { 0, FALSE }; \ No newline at end of file + +void encode_oer_length(size_t num_bytes, TTCN_Buffer& buf, boolean seof) { + if (num_bytes < 128 && seof == FALSE) { + buf.put_c(num_bytes); + } else { + size_t bytes = num_bytes; + // Encode length in maybe more than 1 bytes + size_t needed_bytes = 0; + while (bytes != 0) { + bytes >>= 8; + needed_bytes++; + } + char c = 0; + if (seof == FALSE) { + c |= 1 << 7; + } + c+= needed_bytes; + buf.put_c(c); + for (int i = needed_bytes - 1; i >= 0; i--) { + buf.put_c(static_cast<unsigned char>(num_bytes >> i*8)); + } + } +} + +size_t decode_oer_length(TTCN_Buffer& buf, boolean seof) { + const unsigned char* uc = buf.get_read_data(); + buf.increase_pos(1); + + size_t num_bytes = 0; + if (uc[0] & 0x80 || seof == TRUE) { + size_t bytes = uc[0] & (seof == FALSE ? 0x7F : 0xFF); + for (size_t i = 1; i < bytes+1; i++) { + num_bytes += uc[i] << (bytes-i)*8; + } + buf.increase_pos(bytes); + } else { + // its length is encoded in the last 7 bytes + num_bytes = *uc & 0x7F; + } + return num_bytes; +} + +void encode_oer_tag(const ASN_BERdescriptor_t& descr, TTCN_Buffer& buf) { + char c; + switch(descr.tags[descr.n_tags-1].tagclass) { + case ASN_TAG_UNIV: + c = 0; + break; + case ASN_TAG_APPL: + c = 1 << 6; + break; + case ASN_TAG_CONT: + c = 1 << 7; + break; + case ASN_TAG_PRIV: + c = 3 << 6; + break; + default: + TTCN_error("Incorrect tagclass while encoding OER tag."); + } + + unsigned int tagnum = descr.tags[descr.n_tags-1].tagnumber; + if (tagnum < 63) { + c += tagnum; + buf.put_c(c); + } else { + c += 63; // set every bit to 1 from 6 to 1 bit + buf.put_c(c); + int first_bit_pos = 8*sizeof(unsigned int) - 1; + for (; first_bit_pos != 0; first_bit_pos--) { + if ((tagnum >> first_bit_pos) & 1) { + break; + } + } + size_t needed_bytes = first_bit_pos / 7 + 1;// todo test 0 + unsigned char * uc = (unsigned char*)Malloc(needed_bytes * sizeof(unsigned char)); + size_t buf_pos = 0; + uc[buf_pos] = 0; + int pos = first_bit_pos % 7; + while (first_bit_pos > -1) { + + uc[buf_pos] += ((tagnum >> first_bit_pos) & 1) << (pos); + pos--; + if (pos == -1) { + pos = 6; + if (buf_pos != needed_bytes - 1) { + uc[buf_pos] |= 1 << 7; + } + buf_pos++; + if (buf_pos != needed_bytes) { + uc[buf_pos] = 0; + } + } + first_bit_pos--; + } + buf.put_s(needed_bytes, uc); + Free(uc); + } +} + +ASN_Tag_t decode_oer_tag(TTCN_Buffer& buf) { + ASN_Tag_t tag; + const unsigned char * uc = buf.get_read_data(); + int tagclass = (uc[0] & 0xC0) >> 6; + switch (tagclass) { + case 0: + tag.tagclass = ASN_TAG_UNIV; + break; + case 1: + tag.tagclass = ASN_TAG_APPL; + break; + case 2: + tag.tagclass = ASN_TAG_CONT; + break; + case 3: + tag.tagclass = ASN_TAG_PRIV; + break; + default: + tag.tagclass = ASN_TAG_UNDEF; + break; + } + + buf.increase_pos(1); + if ((uc[0] & 0x3F) != 0x3F) { + // Encoded on 6 bits + tag.tagnumber = (uc[0] & 0x3F); + } else { + size_t tagnumber = 0; + // Encoded on multiple bytes + size_t buf_pos = 1; + // If more bytes to follow + while (uc[buf_pos] & 0x80) { + tagnumber += uc[buf_pos] & 0x7F; + tagnumber <<= 7; + buf_pos++; + } + tagnumber += uc[buf_pos]; + tag.tagnumber = tagnumber; + buf.increase_pos(buf_pos); + } + return tag; +} + +const TTCN_OERdescriptor_t BOOLEAN_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t INTEGER_oer_ = { -1, TRUE, 0, FALSE }; + +const TTCN_OERdescriptor_t BITSTRING_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t OCTETSTRING_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t FLOAT_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t ASN_NULL_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t IA5String_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t VisibleString_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t NumericString_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t PrintableString_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t BMPString_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t UniversalString_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t UTF8String_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t TeletexString_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t VideotexString_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t GraphicString_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t GeneralString_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t OBJID_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t ASN_ROID_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t EMBEDDED_PDV_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t EXTERNAL_oer_ = { 0, FALSE, -1, FALSE }; + +const TTCN_OERdescriptor_t ObjectDescriptor_oer_ = { 0, FALSE, -1, FALSE }; \ No newline at end of file diff --git a/core/OER.hh b/core/OER.hh index f60910847422e388b568ad99941469b4a91c5812..d1bbab55d5bd00ab5768c4dd842e9409c451461a 100644 --- a/core/OER.hh +++ b/core/OER.hh @@ -13,14 +13,57 @@ #define OER_HH #include "Types.h" +#include "Vector.hh" + +class TTCN_Buffer; +class ASN_BERdescriptor_t; +class ASN_Tag_t; struct TTCN_OERdescriptor_t { int bytes; boolean signed_; + int length; + boolean extendable; // Always false. Possibly a bug with is_extendable() +}; + +struct OER_struct +{ + OER_struct() : opentype_poses(0), pos(0) {} + Vector<size_t> opentype_poses; + size_t pos; }; +void encode_oer_length(size_t num_bytes, TTCN_Buffer& buf, boolean seof); + +size_t decode_oer_length(TTCN_Buffer& buf, boolean seof); + +void encode_oer_tag(const ASN_BERdescriptor_t& descr, TTCN_Buffer& buf); + +ASN_Tag_t decode_oer_tag(TTCN_Buffer& buf); + extern const TTCN_OERdescriptor_t BOOLEAN_oer_; +extern const TTCN_OERdescriptor_t INTEGER_oer_; +extern const TTCN_OERdescriptor_t BITSTRING_oer_; +extern const TTCN_OERdescriptor_t OCTETSTRING_oer_; +extern const TTCN_OERdescriptor_t FLOAT_oer_; +extern const TTCN_OERdescriptor_t ASN_NULL_oer_; +extern const TTCN_OERdescriptor_t IA5String_oer_; +extern const TTCN_OERdescriptor_t VisibleString_oer_; +extern const TTCN_OERdescriptor_t NumericString_oer_; +extern const TTCN_OERdescriptor_t PrintableString_oer_; +extern const TTCN_OERdescriptor_t BMPString_oer_; +extern const TTCN_OERdescriptor_t UniversalString_oer_; +extern const TTCN_OERdescriptor_t UTF8String_oer_; +extern const TTCN_OERdescriptor_t TeletexString_oer_; +extern const TTCN_OERdescriptor_t VideotexString_oer_; +extern const TTCN_OERdescriptor_t GraphicString_oer_; +extern const TTCN_OERdescriptor_t GeneralString_oer_; +extern const TTCN_OERdescriptor_t OBJID_oer_; +extern const TTCN_OERdescriptor_t ASN_ROID_oer_; +extern const TTCN_OERdescriptor_t EMBEDDED_PDV_oer_; +extern const TTCN_OERdescriptor_t EXTERNAL_oer_; +extern const TTCN_OERdescriptor_t ObjectDescriptor_oer_; #endif /* OER_HH */ diff --git a/core/Objid.cc b/core/Objid.cc index dd09d7b082341d30ea5720b6b810671de58e7c27..68dbf0271465d89a576f646877b9fc68a281ea89 100644 --- a/core/Objid.cc +++ b/core/Objid.cc @@ -28,6 +28,7 @@ #include "../common/static_check.h" #include "Integer.hh" #include "Optional.hh" +#include "OER.hh" static const size_t MIN_COMPONENTS = 2; @@ -309,6 +310,12 @@ void OBJID::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); @@ -362,6 +369,13 @@ void OBJID::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, , p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); @@ -663,6 +677,83 @@ int OBJID::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, return (int)dec_len; } +int OBJID::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound object identifier value."); + return -1; + } + ASN_BER_TLV_t* new_tlv= BER_encode_TLV(p_td,0); + unsigned char *Vptr=new_tlv->V.str.Vstr; + encode_oer_length(new_tlv->V.str.Vlen, p_buf, FALSE); + p_buf.put_s(new_tlv->V.str.Vlen, Vptr); + ASN_BER_TLV_t::destruct(new_tlv, FALSE); + return 0; +} + +int OBJID::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct&) { + // The same as BER + TTCN_EncDec_ErrorContext ec("While decoding OBJID type: "); + boolean eoc=FALSE; // end-of-component + int i=0; + unsigned long long ull=0; + STATIC_ASSERT(sizeof(ull) > sizeof(objid_element)); + size_t bytes = decode_oer_length(p_buf, FALSE); + const unsigned char* Vptr = p_buf.get_read_data(); + boolean err_repr=FALSE; + while (Vptr < p_buf.get_read_data() + bytes) { + ull |= *Vptr & 0x7F; + if ((*Vptr & 0x80) && err_repr==FALSE) { // not-eoc + if (ull & unsigned_llong_7msb) { + ec.error(TTCN_EncDec::ET_REPR, + "Value of the #%d component is too big.", i+1); + err_repr=TRUE; + } + ull<<=7; + eoc=FALSE; + } + else { // eoc + if (i==0 && p_td.asnbasetype==TTCN_Typedescriptor_t::OBJID) { + // first two component of objid + switch(ull/40ul) { + case 0: + (*this)[0]=0; break; + case 1: + (*this)[0]=1; break; + default: + (*this)[0]=2; break; + } + (*this)[1]=(int)(ull-40*(*this)[0]); + i=1; + } + else { // other components (>2) + // objid_element is UINT/ULONG; the result of the cast is Uxxx_MAX. + // It's computed at compile time. + if(ull > ((objid_element)-1)) { + if(err_repr==FALSE) + ec.error(TTCN_EncDec::ET_REPR, + "Value of the #%d component is too big.", i+1); + (*this)[i]=(objid_element)-1; + // remember the first overflow + if (val_ptr->overflow_idx < 0) val_ptr->overflow_idx = i; + } // if ul too big + else + (*this)[i]=(objid_element)ull; + } + err_repr=FALSE; + ull=0; + eoc=TRUE; + i++; + } // eoc + Vptr++; + } // while Vptr... + if(eoc==FALSE) + ec.error(TTCN_EncDec::ET_INVAL_MSG, + "The last component (#%d) is unterminated.", i+1); + p_buf.increase_pos(bytes); + return 0; +} + void OBJID_template::clean_up() { if (template_selection == VALUE_LIST || diff --git a/core/Objid.hh b/core/Objid.hh index 374009ef73cbeba2c8314b15d970c77ce97923ce..db7901d784b0e3723e585f38a24d5afa9f804d0e 100644 --- a/core/Objid.hh +++ b/core/Objid.hh @@ -115,6 +115,14 @@ public: /** Decodes accordingly to the JSON decoding rules. * Returns the length of the encoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + + /** Encodes accordingly to the OER encoding rules. + * Returns the length of the encoded data. */ + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Decodes accordingly to the OER decoding rules. + * Returns the length of the encoded data. */ + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); }; // objid template class diff --git a/core/Octetstring.cc b/core/Octetstring.cc index c40cb88a65e4b1c218570444cf51c223cf577ebf..6973c7290d32c7bcda690283566c65a45db1bfd0 100644 --- a/core/Octetstring.cc +++ b/core/Octetstring.cc @@ -37,6 +37,7 @@ #include "Optional.hh" #include "../common/dbgnew.hh" +#include "OER.hh" #include <string.h> #include <ctype.h> @@ -653,6 +654,12 @@ void OCTETSTRING::encode(const TTCN_Typedescriptor_t& p_td, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); @@ -740,6 +747,13 @@ void OCTETSTRING::decode(const TTCN_Typedescriptor_t& p_td, , p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); @@ -1389,6 +1403,36 @@ int OCTETSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& return (int)dec_len; } +int OCTETSTRING::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound octetstring value."); + return -1; + } + if (p_td.oer->length == -1) { + encode_oer_length(lengthof(), p_buf, FALSE); + } + p_buf.put_os(*this); + return 0; +} + + +int OCTETSTRING::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct&) { + size_t bytes; + if (p_td.oer->length == -1) { + bytes = decode_oer_length(p_buf, FALSE); + } else { + bytes = p_td.oer->length; + } + init_struct(bytes); + const unsigned char* uc = p_buf.get_read_data(); + for (size_t i = 0; i < bytes; i++) { + val_ptr->octets_ptr[i] = uc[i]; + } + p_buf.increase_pos(bytes); + return 0; +} + // octetstring element class OCTETSTRING_ELEMENT::OCTETSTRING_ELEMENT(boolean par_bound_flag, diff --git a/core/Octetstring.hh b/core/Octetstring.hh index 76f259b78c1b3e28cd9d98dd9ed1089b41dc5b25..3323c9c3b6df40f4180342faed8cb5d0b36e622a 100644 --- a/core/Octetstring.hh +++ b/core/Octetstring.hh @@ -192,6 +192,14 @@ public: /** Decodes accordingly to the JSON encoding rules. * Returns the length of the decoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + + /** Encodes accordingly to the OER encoding rules. + * Returns the length of the encoded data. */ + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Decodes accordingly to the JSON encoding rules. + * Returns the length of the decoded data. */ + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); }; diff --git a/core/Optional.hh b/core/Optional.hh index 23ee70e27844fa0d548b2c62e52bea154e7fce67..cbddc0bca123fcf1bc09b35736ad770c3946468c 100644 --- a/core/Optional.hh +++ b/core/Optional.hh @@ -330,6 +330,8 @@ public: boolean no_err=FALSE, boolean first_call=TRUE); int JSON_encode_negtest(const Erroneous_descriptor_t*, const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const; + int OER_encode_negtest(const Erroneous_descriptor_t*, + const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; #endif /** Encodes accordingly to the JSON encoding rules. @@ -340,6 +342,16 @@ public: * Returns the length of the decoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + /** Encodes accordingly to the OER encoding rules. + * Returns the length of the encoded data. */ + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + /** Decodes accordingly to the OER encoding rules. + * Returns the length of the decoded data. */ + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); + + void OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer); + #ifdef TITAN_RUNTIME_2 /** Called before an element of an optional record of/set of is indexed and passed as an * 'inout' or 'out' parameter to a function (only in Runtime2). @@ -890,6 +902,58 @@ int OPTIONAL<T_type>::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokeni return dec_len; } +template<typename T_type> +int OPTIONAL<T_type>::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const +{ +#ifdef TITAN_RUNTIME_2 + switch(get_selection()) { +#else + switch(optional_selection) { +#endif + case OPTIONAL_PRESENT: + return optional_value->OER_encode(p_td, p_buf); + case OPTIONAL_OMIT: + return 0; + case OPTIONAL_UNBOUND: + default: + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound optional value."); + return -1; + } +} + +#ifdef TITAN_RUNTIME_2 +template<typename T_type> +int OPTIONAL<T_type>::OER_encode_negtest(const Erroneous_descriptor_t*, + const TTCN_Typedescriptor_t&, + TTCN_Buffer&) const +{ +// TODO + return 0; +} +#endif + +template<typename T_type> +int OPTIONAL<T_type>::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer) +{ + set_to_present(); + optional_value->OER_decode(p_td, p_buf, p_oer); + return 0; +} + +template<typename T_type> +void OPTIONAL<T_type>::OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer) +{ +#ifdef TITAN_RUNTIME_2 + if (is_present()) { + optional_selection = OPTIONAL_PRESENT; +#else + if (optional_selection==OPTIONAL_PRESENT) { +#endif + optional_value->OER_decode_opentypes(p_typelist, p_buf, p_oer); + } +} + #ifdef TITAN_RUNTIME_2 template<typename T_type> void OPTIONAL<T_type>::add_refd_index(int index) diff --git a/core/Universal_charstring.cc b/core/Universal_charstring.cc index 3bb4fb6c1d78a983bde3b25034c6e23ff57e2af3..86465842b12ebfdd7f4b102a93954c2dbdd52858 100644 --- a/core/Universal_charstring.cc +++ b/core/Universal_charstring.cc @@ -38,6 +38,7 @@ #include "Addfunc.hh" // for unichar2int #include "TEXT.hh" #include "Optional.hh" +#include "OER.hh" #include <string> #include <iostream> #include <stdint.h> @@ -1174,6 +1175,12 @@ void UNIVERSAL_CHARSTRING::encode(const TTCN_Typedescriptor_t& p_td, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break; } + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); @@ -1259,6 +1266,13 @@ void UNIVERSAL_CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td, , p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); @@ -2609,6 +2623,118 @@ int UNIVERSAL_CHARSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_To return (int)dec_len; } +int UNIVERSAL_CHARSTRING::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound universal charstring value."); + return -1; + } + if (charstring) + const_cast<UNIVERSAL_CHARSTRING&>(*this).convert_cstr_to_uni(); + TTCN_Buffer buf; + switch(p_td.asnbasetype) { + case TTCN_Typedescriptor_t::TELETEXSTRING: + buf.put_os(TTCN_TeletexString_2_ISO2022(*this)); + break; + case TTCN_Typedescriptor_t::VIDEOTEXSTRING: + buf.put_os(TTCN_VideotexString_2_ISO2022(*this)); + break; + case TTCN_Typedescriptor_t::GRAPHICSTRING: + buf.put_os(TTCN_GraphicString_2_ISO2022(*this)); + break; + case TTCN_Typedescriptor_t::GENERALSTRING: + buf.put_os(TTCN_GeneralString_2_ISO2022(*this)); + break; + case TTCN_Typedescriptor_t::UNIVERSALSTRING: + for(int i=0; i<val_ptr->n_uchars; i++) { + buf.put_c(val_ptr->uchars_ptr[i].uc_group); + buf.put_c(val_ptr->uchars_ptr[i].uc_plane); + buf.put_c(val_ptr->uchars_ptr[i].uc_row); + buf.put_c(val_ptr->uchars_ptr[i].uc_cell); + } + break; + case TTCN_Typedescriptor_t::BMPSTRING: + for(int i=0; i<val_ptr->n_uchars; i++) { + buf.put_c(val_ptr->uchars_ptr[i].uc_row); + buf.put_c(val_ptr->uchars_ptr[i].uc_cell); + } + break; + case TTCN_Typedescriptor_t::UTF8STRING: + encode_utf8(buf); + break; + default: + TTCN_EncDec_ErrorContext::error_internal + ("Missing/wrong basetype info for type '%s'.", p_td.name); + } + if (p_td.oer->length == -1) { + encode_oer_length(buf.get_len(), p_buf, FALSE); + } + p_buf.put_buf(buf); + return 0; +} + +int UNIVERSAL_CHARSTRING::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct&) { + size_t bytes; + if (p_td.oer->length == -1) { + bytes = decode_oer_length(p_buf, FALSE); + } else { + bytes = p_td.oer->length; + } + OCTETSTRING ostr(bytes, p_buf.get_read_data()); + const unsigned char* os=ostr; + switch(p_td.asnbasetype) { + case TTCN_Typedescriptor_t::TELETEXSTRING: + *this=TTCN_ISO2022_2_TeletexString(ostr); + break; + case TTCN_Typedescriptor_t::VIDEOTEXSTRING: + *this=TTCN_ISO2022_2_VideotexString(ostr); + break; + case TTCN_Typedescriptor_t::GRAPHICSTRING: + *this=TTCN_ISO2022_2_GraphicString(ostr); + break; + case TTCN_Typedescriptor_t::GENERALSTRING: + *this=TTCN_ISO2022_2_GeneralString(ostr); + break; + case TTCN_Typedescriptor_t::UNIVERSALSTRING: { + if(bytes%4) + TTCN_EncDec_ErrorContext::error + (TTCN_EncDec::ET_DEC_UCSTR, "Length of UCS-4-coded character" + " string is not multiple of 4."); + int ucs_len=bytes/4; + init_struct(ucs_len); + for(int i=0; i<ucs_len; i++) { + val_ptr->uchars_ptr[i].uc_group=os[0]; + val_ptr->uchars_ptr[i].uc_plane=os[1]; + val_ptr->uchars_ptr[i].uc_row=os[2]; + val_ptr->uchars_ptr[i].uc_cell=os[3]; + os+=4; + } + break; } + case TTCN_Typedescriptor_t::BMPSTRING: { + if(bytes%2) + TTCN_EncDec_ErrorContext::error + (TTCN_EncDec::ET_DEC_UCSTR, "Length of UCS-2-coded character" + " string is not multiple of 2."); + int ucs_len=bytes/2; + init_struct(ucs_len); + for(int i=0; i<ucs_len; i++) { + val_ptr->uchars_ptr[i].uc_group=0; + val_ptr->uchars_ptr[i].uc_plane=0; + val_ptr->uchars_ptr[i].uc_row=os[0]; + val_ptr->uchars_ptr[i].uc_cell=os[1]; + os+=2; + } + break; } + case TTCN_Typedescriptor_t::UTF8STRING: + decode_utf8(bytes, os); + break; + default: + TTCN_EncDec_ErrorContext::error_internal + ("Missing/wrong basetype info for type '%s'.", p_td.name); + } // switch + p_buf.increase_pos(bytes); + return 0; +} static void fill_continuing_octets(int n_continuing, unsigned char *continuing_ptr, int n_octets, diff --git a/core/Universal_charstring.hh b/core/Universal_charstring.hh index d0ac3728b32a8e7b8e5a957e868b2fbb01a49029..3888721fda2823d21bd24a5d1423ff1218d0c052 100644 --- a/core/Universal_charstring.hh +++ b/core/Universal_charstring.hh @@ -405,6 +405,10 @@ public: * Returns the length of the decoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); + int OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const; + + int OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&); + /** Converts a string containing a character coding format to its corresponding * enum value. * @param coding_str string containing the coding format diff --git a/core2/Basetype2.cc b/core2/Basetype2.cc index 6680a650e2b953eb03a9554c3720541b68434af4..47d760eeb4001a50b68616d7d095c2d24ef5f576 100644 --- a/core2/Basetype2.cc +++ b/core2/Basetype2.cc @@ -35,6 +35,7 @@ #include "Universal_charstring.hh" #include "Addfunc.hh" #include "PreGenRecordOf.hh" +#include "Encdec.hh" //////////////////////////////////////////////////////////////////////////////// @@ -196,6 +197,13 @@ int Base_Type::JSON_encode_negtest_raw(JSON_Tokenizer&) const return 0; } +int Base_Type::OER_encode_negtest_raw(JSON_Tokenizer&) const +{ + TTCN_error("A value of type %s cannot be used as erroneous raw value for OER encoding.", + get_descriptor()->name); + return 0; +} + int Base_Type::XER_encode_negtest(const Erroneous_descriptor_t* /*p_err_descr*/, const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, unsigned int flavor2, int indent, embed_values_enc_struct_t*) const { @@ -216,6 +224,13 @@ int Base_Type::JSON_encode_negtest(const Erroneous_descriptor_t* /*p_err_descr*/ return 0; } +int Base_Type::OER_encode_negtest(const Erroneous_descriptor_t* /*p_err_descr*/, + const TTCN_Typedescriptor_t& /*p_td*/, TTCN_Buffer& /*p_tok*/) const +{ + TTCN_error("Internal error: calling Base_Type::OER_encode_negtest()."); + return 0; +} + #else #error this is for RT2 only #endif @@ -1650,6 +1665,45 @@ int Record_Of_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenize return (int)dec_len; } +int Record_Of_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound %s of value.", is_set() ? "set" : "record"); + return -1; + } + encode_oer_length(get_nof_elements(), p_buf, TRUE); + for (int i = 0; i < get_nof_elements(); i++) { + get_at(i)->OER_encode(*p_td.oftype_descr, p_buf); + } + return 0; +} + +int Record_Of_Type::OER_encode_negtest(const Erroneous_descriptor_t*, const TTCN_Typedescriptor_t&, TTCN_Buffer&) const { + //TODO + return 0; +} + +int Record_Of_Type::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer) { + size_t nof_elements = decode_oer_length(p_buf, TRUE); + set_size(nof_elements); + for (size_t i = 0; i < nof_elements; i++) { + get_at(i)->OER_decode(*p_td.oftype_descr, p_buf, p_oer); + } + return 0; +} + +void Record_Of_Type::OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer) +{ + p_typelist.push(this); + TTCN_EncDec_ErrorContext ec_0("Component #"); + TTCN_EncDec_ErrorContext ec_1; + for(int elem_i=0; elem_i<get_nof_elements(); elem_i++) { + ec_1.set_msg("%d: ", elem_i); + get_at(elem_i)->OER_decode_opentypes(p_typelist, p_buf, p_oer); + } + p_typelist.pop(); +} + void Record_Of_Type::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const { @@ -1695,6 +1749,12 @@ void Record_Of_Type::encode(const TTCN_Typedescriptor_t& p_td, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); } @@ -1768,6 +1828,13 @@ void Record_Of_Type::decode(const TTCN_Typedescriptor_t& p_td, "because invalid or incomplete message was received", p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); } @@ -2875,6 +2942,12 @@ void Record_Type::encode(const TTCN_Typedescriptor_t& p_td, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); } @@ -2965,6 +3038,13 @@ void Record_Type::decode(const TTCN_Typedescriptor_t& p_td, " message was received", p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); } @@ -6067,6 +6147,106 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& return (int)dec_len; } +int Record_Type::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound %s value.", is_set() ? "set" : "record"); + return -1; + } + int next_default_idx = 0; + const default_struct* default_indexes = get_default_indexes(); + int field_count = get_count(); + int pos = 8; + char c = 0; + for (int i = 0; i < field_count; i++) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==i); + if (is_default_field) { + next_default_idx++; + } + if (get_at(i)->is_optional() || is_default_field) { + pos--; + c += get_at(i)->is_present() << pos; + if (pos == 0) { + p_buf.put_c(c); + pos = 8; + c = 0; + } + } + } + if (pos != 8) { + p_buf.put_c(c); + } + for (int i = 0; i < field_count; ++i) { + get_at(i)->OER_encode(*fld_descr(i), p_buf); + } + return 0; +} + +int Record_Type::OER_encode_negtest(const Erroneous_descriptor_t*, const TTCN_Typedescriptor_t&, TTCN_Buffer&) const { + //TODO + return 0; +} + +int Record_Type::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer) { + int field_count = get_count(); + size_t nof_opt = 0; + int next_default_idx = 0; + const default_struct* default_indexes = get_default_indexes(); + for (int i = 0; i < field_count; i++) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==i); + if (is_default_field) { + next_default_idx++; + } + if (get_at(i)->is_optional() || is_default_field) { + nof_opt++; + } + } + size_t act_pos = 0; + size_t bytes = nof_opt / 8 + (nof_opt % 8 == 0 ? 0 : 1); + const unsigned char* uc = p_buf.get_read_data(); + p_buf.increase_pos(bytes); + next_default_idx = 0; + for (int i = 0; i < field_count; ++i) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==i); + if (is_default_field) { + next_default_idx++; + } + if (get_at(i)->is_optional() || is_default_field) { + if (!(uc[0] & 1 << (7-act_pos))) { + get_at(i)->set_to_omit(); + } else { + get_at(i)->OER_decode(*fld_descr(i), p_buf, p_oer); + } + act_pos++; + if (act_pos == 8) { + uc = uc + 1; + act_pos = 0; + } + } else { + get_at(i)->OER_decode(*fld_descr(i), p_buf, p_oer); + } + } + if (is_opentype_outermost()) { + TTCN_EncDec_ErrorContext ec_1("While decoding opentypes: "); + TTCN_Type_list p_typelist; + OER_decode_opentypes(p_typelist, p_buf, p_oer); + } /* if sdef->opentype_outermost */ + return 0; +} + +void Record_Type::OER_decode_opentypes(TTCN_Type_list& p_typelist, TTCN_Buffer& p_buf, OER_struct& p_oer) +{ + p_typelist.push(this); + TTCN_EncDec_ErrorContext ec_0("Component '"); + TTCN_EncDec_ErrorContext ec_1; + int field_cnt = get_count(); + for(int i=0; i<field_cnt; i++) { + ec_1.set_msg("%s': ", fld_name(i)); + get_at(i)->OER_decode_opentypes(p_typelist, p_buf, p_oer); + } /* for i */ + p_typelist.pop(); +} + //////////////////////////////////////////////////////////////////////////////// Empty_Record_Type::Empty_Record_Type(): bound_flag(FALSE) @@ -6190,6 +6370,12 @@ void Empty_Record_Type::encode(const TTCN_Typedescriptor_t& p_td, JSON_encode(p_td, tok); p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-encoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_encode(p_td, p_buf); + break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name); } @@ -6267,6 +6453,13 @@ void Empty_Record_Type::decode(const TTCN_Typedescriptor_t& p_td, " message was received", p_td.name); p_buf.set_pos(tok.get_buf_pos()); break;} + case TTCN_EncDec::CT_OER: { + TTCN_EncDec_ErrorContext ec("While OER-decoding type '%s': ", p_td.name); + if(!p_td.oer) TTCN_EncDec_ErrorContext::error_internal( + "No OER descriptor available for type '%s'.", p_td.name); + OER_struct p_oer; + OER_decode(p_td, p_buf, p_oer); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); } @@ -6440,6 +6633,20 @@ int Empty_Record_Type::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& return (int)dec_len; } +int Empty_Record_Type::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&) const { + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound empty %s value.", is_set() ? "set" : "record"); + return -1; + } + return 0; +} + +int Empty_Record_Type::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, OER_struct&) { + bound_flag = TRUE; + return 0; +} + boolean operator==(null_type /*null_value*/, const Empty_Record_Type& other_value) { if (!other_value.is_bound()) diff --git a/regression_test/OER/Makefile b/regression_test/OER/Makefile index 178fa514460ebcb7ee366eca6ac4b613a692e9da..21fda14a38b02c23c0fea6dacd04ffff24e9b223 100644 --- a/regression_test/OER/Makefile +++ b/regression_test/OER/Makefile @@ -15,7 +15,7 @@ include $(TOPDIR)/Makefile.regression .SUFFIXES: .ttcn .asn .hh .PHONY: all clean dep run -TTCN3_LIB = ttcn3$(RT2_SUFFIX)-parallel$(DYNAMIC_SUFFIX) +TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) TTCN3_MODULES = OER.ttcn @@ -48,10 +48,10 @@ compile: $(TTCN3_MODULES) $(ASN1_MODULES) $(TTCN3_COMPILER) $(COMPILER_FLAGS) $^ clean distclean: - $(RM) $(TARGET) $(GENERATED_HEADERS) $(GENERATED_SOURCES) $(OBJECTS) *.log Makefile.bak + $(RM) $(TARGET) $(GENERATED_HEADERS) $(GENERATED_SOURCES) $(OBJECTS) *.log Makefile.bak compile dep: $(GENERATED_SOURCES) makedepend $(CPPFLAGS) $(GENERATED_SOURCES) run: $(TARGET) - $(TTCN3_DIR)/bin/ttcn3_start $(TARGET) OER.cfg + ./$(TARGET) OER.cfg diff --git a/regression_test/OER/OER.ttcn b/regression_test/OER/OER.ttcn index c701e82dcc18cbd99497eb56b48dabd2086d6caa..f8b4c8b383edc8fab849c687c0b4a2b971250887 100644 --- a/regression_test/OER/OER.ttcn +++ b/regression_test/OER/OER.ttcn @@ -740,6 +740,2062 @@ setverdict(fail, "tc_integer: ", match(s8i, s8ires)); } + setverdict(pass); + } + + + external function enc_MyEnum(in MyEnum pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_MyEnum(in octetstring stream) return MyEnum + with { extension "prototype (convert) decode(OER)" } + + testcase tc_enumerated() runs on EmptyCT { + var MyEnum me, meres; + var octetstring os; + + me := e0; + os := enc_MyEnum(me); + if (os != '00'O) { + setverdict(fail, "tc_enumerated: ", match('00'O, os)); + } + meres := dec_MyEnum(os); + if (me != meres) { + setverdict(fail, "tc_enumerated: ", match(me, meres)); + } + + me := e1; + os := enc_MyEnum(me); + if (os != '01'O) { + setverdict(fail, "tc_enumerated: ", match('01'O, os)); + } + meres := dec_MyEnum(os); + if (me != meres) { + setverdict(fail, "tc_enumerated: ", match(me, meres)); + } + + me := e2; + os := enc_MyEnum(me); + if (os != '02'O) { + setverdict(fail, "tc_enumerated: ", match('02'O, os)); + } + meres := dec_MyEnum(os); + if (me != meres) { + setverdict(fail, "tc_enumerated: ", match(me, meres)); + } + + me := ebig; + os := enc_MyEnum(me); + if (os != '8407D3CDE9'O) { + setverdict(fail, "tc_enumerated: ", match('8407D3CDE9'O, os)); + } + meres := dec_MyEnum(os); + if (me != meres) { + setverdict(fail, "tc_enumerated: ", match(me, meres)); + } + + me := esmall; + os := enc_MyEnum(me); + if (os != '84FEB8D1B4'O) { + setverdict(fail, "tc_enumerated: ", match('84FEB8D1B4'O, os)); + } + meres := dec_MyEnum(os); + if (me != meres) { + setverdict(fail, "tc_enumerated: ", match(me, meres)); + } + + setverdict(pass); + } + + + external function enc_BitstringRestricted(in BitstringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_BitstringRestricted(in octetstring stream) return BitstringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_BitstringRestricted2(in BitstringRestricted2 pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_BitstringRestricted2(in octetstring stream) return BitstringRestricted2 + with { extension "prototype (convert) decode(OER)" } + + external function enc_BitstringRestricted3(in BitstringRestricted3 pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_BitstringRestricted3(in octetstring stream) return BitstringRestricted3 + with { extension "prototype (convert) decode(OER)" } + + external function enc_BitstringUnrestricted(in BitstringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_BitstringUnrestricted(in octetstring stream) return BitstringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + testcase tc_bitstring() runs on EmptyCT { + var BitstringRestricted bs, bsres; + var octetstring os; + + bs := '01011101'B; + os := enc_BitstringRestricted(bs); + if (os != '5D'O) { + setverdict(fail, "tc_bitstring: ", match('5D'O, os)); + } + bsres := dec_BitstringRestricted(os); + if (bs != bsres) { + setverdict(fail, "tc_bitstring: ", match(bs, bsres)); + } + + bs := '00000000'B; + os := enc_BitstringRestricted(bs); + if (os != '00'O) { + setverdict(fail, "tc_bitstring: ", match('00'O, os)); + } + bsres := dec_BitstringRestricted(os); + if (bs != bsres) { + setverdict(fail, "tc_bitstring: ", match(bs, bsres)); + } + + bs := '11111111'B; + os := enc_BitstringRestricted(bs); + if (os != 'FF'O) { + setverdict(fail, "tc_bitstring: ", match('FF'O, os)); + } + bsres := dec_BitstringRestricted(os); + if (bs != bsres) { + setverdict(fail, "tc_bitstring: ", match(bs, bsres)); + } + + var BitstringRestricted2 bs2, bs2res; + + bs2 := '010111011'B; + os := enc_BitstringRestricted2(bs2); + if (os != '5D80'O) { + setverdict(fail, "tc_bitstring: ", match('5D80'O, os)); + } + bs2res := dec_BitstringRestricted2(os); + if (bs2 != bs2res) { + setverdict(fail, "tc_bitstring: ", match(bs2, bs2res)); + } + + var BitstringRestricted3 bs3, bs3res; + + bs3 := '110'B; + os := enc_BitstringRestricted3(bs3); + if (os != 'C0'O) { + setverdict(fail, "tc_bitstring: ", match('C0'O, os)); + } + bs3res := dec_BitstringRestricted3(os); + if (bs3 != bs3res) { + setverdict(fail, "tc_bitstring: ", match(bs3, bs3res)); + } + + var BitstringUnrestricted ubs, ubsres; + + ubs := '010111011'B; + os := enc_BitstringUnrestricted(ubs); + if (os != '03075D80'O) { + setverdict(fail, "tc_bitstring: ", match('03075D80'O, os)); + } + ubsres := dec_BitstringUnrestricted(os); + if (ubs != ubsres) { + setverdict(fail, "tc_bitstring: ", match(ubs, ubsres)); + } + + ubs := '010111011010'B; + os := enc_BitstringUnrestricted(ubs); + if (os != '03045DA0'O) { + setverdict(fail, "tc_bitstring: ", match('03045DA0'O, os)); + } + ubsres := dec_BitstringUnrestricted(os); + if (ubs != ubsres) { + setverdict(fail, "tc_bitstring: ", match(ubs, ubsres)); + } + + ubs := ''B; + os := enc_BitstringUnrestricted(ubs); + if (os != '0100'O) { + setverdict(fail, "tc_bitstring: ", match('0100'O, os)); + } + ubsres := dec_BitstringUnrestricted(os); + if (ubs != ubsres) { + setverdict(fail, "tc_bitstring: ", match(ubs, ubsres)); + } + + ubs := '0101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101010101011010101010110101010101101110'B; + os := enc_BitstringUnrestricted(ubs); + if (os != '8201FC0555AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AADC0'O) { + setverdict(fail, "tc_bitstring: ", match('8201FC0555AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AAD55AAB556AADC0'O, os)); + } + ubsres := dec_BitstringUnrestricted(os); + if (ubs != ubsres) { + setverdict(fail, "tc_bitstring: ", match(ubs, ubsres)); + } + + setverdict(pass); + } + + external function enc_OctetstringRestricted(in OctetstringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_OctetstringRestricted(in octetstring stream) return OctetstringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_OctetstringUnrestricted(in OctetstringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_OctetstringUnrestricted(in octetstring stream) return OctetstringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + testcase tc_octetstring() runs on EmptyCT { + var OctetstringRestricted ors, orsres; + var octetstring os; + + ors := 'ABCDABCD'O + os := enc_OctetstringRestricted(ors); + if (os != 'ABCDABCD'O) { + setverdict(fail, "tc_octetstring: ", match('ABCDABCD'O, os)); + } + orsres := dec_OctetstringRestricted(os); + if (ors != orsres) { + setverdict(fail, "tc_octetstring: ", match(ors, orsres)); + } + + ors := '00000000'O + os := enc_OctetstringRestricted(ors); + if (os != '00000000'O) { + setverdict(fail, "tc_octetstring: ", match('00000000'O, os)); + } + orsres := dec_OctetstringRestricted(os); + if (ors != orsres) { + setverdict(fail, "tc_octetstring: ", match(ors, orsres)); + } + + ors := 'FFFFFFFF'O + os := enc_OctetstringRestricted(ors); + if (os != 'FFFFFFFF'O) { + setverdict(fail, "tc_octetstring: ", match('FFFFFFFF'O, os)); + } + orsres := dec_OctetstringRestricted(os); + if (ors != orsres) { + setverdict(fail, "tc_octetstring: ", match(ors, orsres)); + } + + var OctetstringUnrestricted ors2, ors2res; + ors2 := 'ABCDABCD'O + os := enc_OctetstringUnrestricted(ors2); + if (os != '04ABCDABCD'O) { + setverdict(fail, "tc_octetstring: ", match('04ABCDABCD'O, os)); + } + + ors2 := 'ABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFD'O + os := enc_OctetstringUnrestricted(ors2); + if (os != '8201E6ABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFD'O) { + setverdict(fail, "tc_octetstring: ", match('8201E6ABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFDABCD12345678CDAFFD'O, os)); + } + ors2res := dec_OctetstringUnrestricted(os); + if (ors2 != ors2res) { + setverdict(fail, "tc_octetstring: ", match(ors2, ors2res)); + } + + + setverdict(pass); + } + + external function enc_RealUnrestricted(in RealUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_RealUnrestricted(in octetstring stream) return RealUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_RealRestricted(in RealRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_RealRestricted(in octetstring stream) return RealRestricted + with { extension "prototype (convert) decode(OER)" } + + testcase tc_float() runs on EmptyCT { + var RealUnrestricted r, rres; + var octetstring os; + + r := 0.0; + os := enc_RealUnrestricted(r); + if (os != '00'O) { + setverdict(fail, "tc_float: ", match('00'O, os)); + } + rres := dec_RealUnrestricted(os); + if (r != rres) { + setverdict(fail, "tc_float: ", match(r, rres)); + } + + r := 3.14; + os := enc_RealUnrestricted(r); + if (os != '08033331342E452D32'O) { + setverdict(fail, "tc_float: ", match('08033331342E452D32'O, os)); + } + rres := dec_RealUnrestricted(os); + if (r != rres) { + setverdict(fail, "tc_float: ", match(r, rres)); + } + + r := infinity; + os := enc_RealUnrestricted(r); + if (os != '0140'O) { + setverdict(fail, "tc_float: ", match('0140'O, os)); + } + rres := dec_RealUnrestricted(os); + if (r != rres) { + setverdict(fail, "tc_float: ", match(r, rres)); + } + + r := -infinity; + os := enc_RealUnrestricted(r); + if (os != '0141'O) { + setverdict(fail, "tc_float: ", match('0141'O, os)); + } + rres := dec_RealUnrestricted(os); + if (r != rres) { + setverdict(fail, "tc_float: ", match(r, rres)); + } + + r := not_a_number; + os := enc_RealUnrestricted(r); + if (os != '0142'O) { + setverdict(fail, "tc_float: ", match('0142'O, os)); + } + rres := dec_RealUnrestricted(os); + if (r != rres) { + setverdict(fail, "tc_float: ", match(r, rres)); + } + + + // Restricted real is not supported. Decoded as normal real. + var RealRestricted r2, r2res; + + r2 := 3.14; + os := enc_RealRestricted(r2); + if (os != '08033331342E452D32'O) { + setverdict(fail, "tc_float: ", match('08033331342E452D32'O, os)); + } + r2res := dec_RealRestricted(os); + if (r2 != r2res) { + setverdict(fail, "tc_float: ", match(r2, r2res)); + } + + r2 := infinity; + os := enc_RealRestricted(r2); + if (os != '0140'O) { + setverdict(fail, "tc_float: ", match('0140'O, os)); + } + r2res := dec_RealRestricted(os); + if (r2 != r2res) { + setverdict(fail, "tc_float: ", match(r2, r2res)); + } + + r2 := -infinity; + os := enc_RealRestricted(r2); + if (os != '0141'O) { + setverdict(fail, "tc_float: ", match('0141'O, os)); + } + r2res := dec_RealRestricted(os); + if (r2 != r2res) { + setverdict(fail, "tc_float: ", match(r2, r2res)); + } + + r2 := not_a_number; + os := enc_RealRestricted(r2); + if (os != '0142'O) { + setverdict(fail, "tc_float: ", match('0142'O, os)); + } + r2res := dec_RealRestricted(os); + if (r2 != r2res) { + setverdict(fail, "tc_float: ", match(r2, r2res)); + } + + setverdict(pass); + } + + external function enc_NullType(in NullType pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_NullType(in octetstring stream) return NullType + with { extension "prototype (convert) decode(OER)" } + + testcase tc_null() runs on EmptyCT { + var NullType nullv, nullres; + var octetstring os; + + nullv := NULL; + os := enc_NullType(nullv); + if (os != ''O) { + setverdict(fail, "tc_null: ", match(''O, os)); + } + nullres := dec_NullType(os); + if (nullv != nullres) { + setverdict(fail, "tc_null: ", match(nullv, nullres)); + } + + setverdict(pass); + } + + external function enc_IA5StringRestricted(in IA5StringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_IA5StringRestricted(in octetstring stream) return IA5StringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_ISO646StringRestricted(in ISO646StringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ISO646StringRestricted(in octetstring stream) return ISO646StringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_VisibleStringRestricted(in VisibleStringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_VisibleStringRestricted(in octetstring stream) return VisibleStringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_NumericStringRestricted(in NumericStringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_NumericStringRestricted(in octetstring stream) return NumericStringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_PrintableStringRestricted(in PrintableStringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_PrintableStringRestricted(in octetstring stream) return PrintableStringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_IA5StringUnrestricted(in IA5StringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_IA5StringUnrestricted(in octetstring stream) return IA5StringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_ISO646StringUnrestricted(in ISO646StringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ISO646StringUnrestricted(in octetstring stream) return ISO646StringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_VisibleStringUnrestricted(in VisibleStringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_VisibleStringUnrestricted(in octetstring stream) return VisibleStringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_NumericStringUnrestricted(in NumericStringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_NumericStringUnrestricted(in octetstring stream) return NumericStringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_PrintableStringUnrestricted(in PrintableStringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_PrintableStringUnrestricted(in octetstring stream) return PrintableStringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + testcase tc_charstrings() runs on EmptyCT { + var IA5StringRestricted ia5, ia5res; + var octetstring os; + + ia5 := "abcd"; + os := enc_IA5StringRestricted(ia5); + if (os != '61626364'O) { + setverdict(fail, "tc_charstrings: ", match('61626364'O, os)); + } + ia5res := dec_IA5StringRestricted(os); + if (ia5 != ia5res) { + setverdict(fail, "tc_charstrings: ", match(ia5, ia5res)); + } + + ia5 := ".:'%"; + os := enc_IA5StringRestricted(ia5); + if (os != '2E3A2725'O) { + setverdict(fail, "tc_charstrings: ", match('2E3A2725'O, os)); + } + ia5res := dec_IA5StringRestricted(os); + if (ia5 != ia5res) { + setverdict(fail, "tc_charstrings: ", match(ia5, ia5res)); + } + + var ISO646StringRestricted iso, isores; + + iso := "abcd"; + os := enc_ISO646StringRestricted(iso); + if (os != '61626364'O) { + setverdict(fail, "tc_charstrings: ", match('61626364'O, os)); + } + isores := dec_ISO646StringRestricted(os); + if (iso != isores) { + setverdict(fail, "tc_charstrings: ", match(iso, isores)); + } + + iso := ".:'%"; + os := enc_ISO646StringRestricted(iso); + if (os != '2E3A2725'O) { + setverdict(fail, "tc_charstrings: ", match('2E3A2725'O, os)); + } + isores := dec_ISO646StringRestricted(os); + if (iso != isores) { + setverdict(fail, "tc_charstrings: ", match(iso, isores)); + } + + var VisibleStringRestricted vis, visres; + + vis := "abcd"; + os := enc_VisibleStringRestricted(vis); + if (os != '61626364'O) { + setverdict(fail, "tc_charstrings: ", match('61626364'O, os)); + } + visres := dec_VisibleStringRestricted(os); + if (vis != visres) { + setverdict(fail, "tc_charstrings: ", match(vis, visres)); + } + + vis := ".:'%"; + os := enc_VisibleStringRestricted(vis); + if (os != '2E3A2725'O) { + setverdict(fail, "tc_charstrings: ", match('2E3A2725'O, os)); + } + visres := dec_VisibleStringRestricted(os); + if (vis != visres) { + setverdict(fail, "tc_charstrings: ", match(vis, visres)); + } + + var NumericStringRestricted num, numres; + + num := "1234"; + os := enc_NumericStringRestricted(num); + if (os != '31323334'O) { + setverdict(fail, "tc_charstrings: ", match('31323334'O, os)); + } + numres := dec_NumericStringRestricted(os); + if (num != numres) { + setverdict(fail, "tc_charstrings: ", match(num, numres)); + } + + num := " 3 4"; + os := enc_NumericStringRestricted(num); + if (os != '20332034'O) { + setverdict(fail, "tc_charstrings: ", match('20332034'O, os)); + } + numres := dec_NumericStringRestricted(os); + if (num != numres) { + setverdict(fail, "tc_charstrings: ", match(num, numres)); + } + + var PrintableStringRestricted print, printres; + + print := "abcd"; + os := enc_PrintableStringRestricted(print); + if (os != '61626364'O) { + setverdict(fail, "tc_charstrings: ", match('61626364'O, os)); + } + printres := dec_PrintableStringRestricted(os); + if (print != printres) { + setverdict(fail, "tc_charstrings: ", match(print, printres)); + } + + print := ".:'+"; + os := enc_PrintableStringRestricted(print); + if (os != '2E3A272B'O) { + setverdict(fail, "tc_charstrings: ", match('2E3A272B'O, os)); + } + printres := dec_PrintableStringRestricted(os); + if (print != printres) { + setverdict(fail, "tc_charstrings: ", match(print, printres)); + } + + + // Unrestricted cases + var IA5StringUnrestricted ia52, ia52res; + + ia52 := "abcd"; + os := enc_IA5StringUnrestricted(ia52); + if (os != '0461626364'O) { + setverdict(fail, "tc_charstrings: ", match('0461626364'O, os)); + } + ia52res := dec_IA5StringUnrestricted(os); + if (ia52 != ia52res) { + setverdict(fail, "tc_charstrings: ", match(ia52, ia52res)); + } + + ia52 := ".:'%"; + os := enc_IA5StringUnrestricted(ia52); + if (os != '042E3A2725'O) { + setverdict(fail, "tc_charstrings: ", match('042E3A2725'O, os)); + } + ia52res := dec_IA5StringUnrestricted(os); + if (ia5 != ia5res) { + setverdict(fail, "tc_charstrings: ", match(ia52, ia52res)); + } + + var ISO646StringUnrestricted iso2, iso2res; + + iso2 := "abcd"; + os := enc_ISO646StringUnrestricted(iso2); + if (os != '0461626364'O) { + setverdict(fail, "tc_charstrings: ", match('0461626364'O, os)); + } + iso2res := dec_ISO646StringUnrestricted(os); + if (iso2 != iso2res) { + setverdict(fail, "tc_charstrings: ", match(iso2, iso2res)); + } + + iso2 := ".:'%"; + os := enc_ISO646StringUnrestricted(iso2); + if (os != '042E3A2725'O) { + setverdict(fail, "tc_charstrings: ", match('042E3A2725'O, os)); + } + iso2res := dec_ISO646StringUnrestricted(os); + if (iso2 != iso2res) { + setverdict(fail, "tc_charstrings: ", match(iso2, iso2res)); + } + + var VisibleStringUnrestricted vis2, vis2res; + + vis2 := "abcd"; + os := enc_VisibleStringUnrestricted(vis2); + if (os != '0461626364'O) { + setverdict(fail, "tc_charstrings: ", match('0461626364'O, os)); + } + vis2res := dec_VisibleStringUnrestricted(os); + if (vis2 != vis2res) { + setverdict(fail, "tc_charstrings: ", match(vis2, vis2res)); + } + + vis2 := ".:'%"; + os := enc_VisibleStringUnrestricted(vis2); + if (os != '042E3A2725'O) { + setverdict(fail, "tc_charstrings: ", match('042E3A2725'O, os)); + } + vis2res := dec_VisibleStringUnrestricted(os); + if (vis2 != vis2res) { + setverdict(fail, "tc_charstrings: ", match(vis2, vis2res)); + } + + var NumericStringUnrestricted num2, num2res; + + num2 := "1234"; + os := enc_NumericStringUnrestricted(num2); + if (os != '0431323334'O) { + setverdict(fail, "tc_charstrings: ", match('0431323334'O, os)); + } + num2res := dec_NumericStringUnrestricted(os); + if (num2 != num2res) { + setverdict(fail, "tc_charstrings: ", match(num2, num2res)); + } + + num2 := " 3 4"; + os := enc_NumericStringUnrestricted(num2); + if (os != '0420332034'O) { + setverdict(fail, "tc_charstrings: ", match('0420332034'O, os)); + } + num2res := dec_NumericStringUnrestricted(os); + if (num2 != num2res) { + setverdict(fail, "tc_charstrings: ", match(num2, num2res)); + } + + var PrintableStringUnrestricted print2, print2res; + + print2 := "abcd"; + os := enc_PrintableStringUnrestricted(print2); + if (os != '0461626364'O) { + setverdict(fail, "tc_charstrings: ", match('0461626364'O, os)); + } + print2res := dec_PrintableStringUnrestricted(os); + if (print2 != print2res) { + setverdict(fail, "tc_charstrings: ", match(print2, print2res)); + } + + print2 := ".:'+"; + os := enc_PrintableStringUnrestricted(print2); + if (os != '042E3A272B'O) { + setverdict(fail, "tc_charstrings: ", match('042E3A272B'O, os)); + } + print2res := dec_PrintableStringUnrestricted(os); + if (print2 != print2res) { + setverdict(fail, "tc_charstrings: ", match(print2, print2res)); + } + + setverdict(pass); + + } + + external function enc_BMPStringRestricted(in BMPStringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_BMPStringRestricted(in octetstring stream) return BMPStringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_UniversalStringRestricted(in UniversalStringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_UniversalStringRestricted(in octetstring stream) return UniversalStringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_UTF8StringRestricted(in UTF8StringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_UTF8StringRestricted(in octetstring stream) return UTF8StringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_TeletexStringRestricted(in TeletexStringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_TeletexStringRestricted(in octetstring stream) return TeletexStringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_T61StringRestricted(in T61StringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_T61StringRestricted(in octetstring stream) return T61StringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_VideotexStringRestricted(in VideotexStringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_VideotexStringRestricted(in octetstring stream) return VideotexStringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_GraphicStringRestricted(in GraphicStringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_GraphicStringRestricted(in octetstring stream) return GraphicStringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_GeneralStringRestricted(in GeneralStringRestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_GeneralStringRestricted(in octetstring stream) return GeneralStringRestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_BMPStringUnrestricted(in BMPStringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_BMPStringUnrestricted(in octetstring stream) return BMPStringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_UniversalStringUnrestricted(in UniversalStringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_UniversalStringUnrestricted(in octetstring stream) return UniversalStringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_UTF8StringUnrestricted(in UTF8StringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_UTF8StringUnrestricted(in octetstring stream) return UTF8StringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_TeletexStringUnrestricted(in TeletexStringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_TeletexStringUnrestricted(in octetstring stream) return TeletexStringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_T61StringUnrestricted(in T61StringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_T61StringUnrestricted(in octetstring stream) return T61StringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_VideotexStringUnrestricted(in VideotexStringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_VideotexStringUnrestricted(in octetstring stream) return VideotexStringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_GraphicStringUnrestricted(in GraphicStringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_GraphicStringUnrestricted(in octetstring stream) return GraphicStringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + external function enc_GeneralStringUnrestricted(in GeneralStringUnrestricted pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_GeneralStringUnrestricted(in octetstring stream) return GeneralStringUnrestricted + with { extension "prototype (convert) decode(OER)" } + + testcase tc_universal_charstring() runs on EmptyCT { + var BMPStringRestricted bs, bsres; + var octetstring os; + + bs := "abcd"; + os := enc_BMPStringRestricted(bs); + if (os != '0061006200630064'O) { + setverdict(fail, "tc_universal_charstring: ", match('0061006200630064'O, os)); + } + bsres := dec_BMPStringRestricted(os); + if (bs != bsres) { + setverdict(fail, "tc_charstrings: ", match(bs, bsres)); + } + + bs := ".:'" & char(0,0,64,42); + os := enc_BMPStringRestricted(bs); + if (os != '002E003A0027402A'O) { + setverdict(fail, "tc_universal_charstring: ", match('002E003A0027402A'O, os)); + } + bsres := dec_BMPStringRestricted(os); + if (bs != bsres) { + setverdict(fail, "tc_charstrings: ", match(bs, bsres)); + } + + var UniversalStringRestricted us, usres; + + us := "abcd"; + os := enc_UniversalStringRestricted(us); + if (os != '00000061000000620000006300000064'O) { + setverdict(fail, "tc_universal_charstring: ", match('00000061000000620000006300000064'O, os)); + } + usres := dec_UniversalStringRestricted(os); + if (us != usres) { + setverdict(fail, "tc_charstrings: ", match(us, usres)); + } + + us := ".:'" & char(2,5,64,42); + os := enc_UniversalStringRestricted(us); + if (os != '0000002E0000003A000000270205402A'O) { + setverdict(fail, "tc_universal_charstring: ", match('0000002E0000003A000000270205402A'O, os)); + } + usres := dec_UniversalStringRestricted(os); + if (us != usres) { + setverdict(fail, "tc_charstrings: ", match(us, usres)); + } + + var UTF8StringRestricted uts, utsres; + + uts := "abcd"; + os := enc_UTF8StringRestricted(uts); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + utsres := dec_UTF8StringRestricted(os); + if (uts != utsres) { + setverdict(fail, "tc_charstrings: ", match(uts, utsres)); + } + + uts := ".:'" & char(2,5,64,42); + os := enc_UTF8StringRestricted(uts); + if (os != '082E3A27FA819480AA'O) { + setverdict(fail, "tc_universal_charstring: ", match('082E3A27FA819480AA'O, os)); + } + utsres := dec_UTF8StringRestricted(os); + if (uts != utsres) { + setverdict(fail, "tc_charstrings: ", match(uts, utsres)); + } + + /*var TeletexStringRestricted ts, tsres; + + ts := "ttxx"; + os := enc_TeletexStringRestricted(ts); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + tsres := dec_TeletexStringRestricted(os); + if (ts != tsres) { + setverdict(fail, "tc_charstrings: ", match(ts, tsres)); + } + + ts := ".:'" & char(2,5,64,42); + os := enc_TeletexStringRestricted(ts); + if (os != '082E3A27FA819480AA'O) { + setverdict(fail, "tc_universal_charstring: ", match('082E3A27FA819480AA'O, os)); + } + tsres := dec_TeletexStringRestricted(os); + if (ts != tsres) { + setverdict(fail, "tc_charstrings: ", match(ts, tsres)); + } + + var T61StringRestricted t61s, t61sres; + + t61s := "ttxx"; + os := enc_T61StringRestricted(t61s); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + t61sres := dec_T61StringRestricted(os); + if (t61s != t61sres) { + setverdict(fail, "tc_charstrings: ", match(t61s, t61sres)); + } + + t61s := ".:'" & char(2,5,64,42); + os := enc_T61StringRestricted(t61s); + if (os != '082E3A27FA819480AA'O) { + setverdict(fail, "tc_universal_charstring: ", match('082E3A27FA819480AA'O, os)); + } + t61sres := dec_T61StringRestricted(os); + if (t61s != t61sres) { + setverdict(fail, "tc_charstrings: ", match(t61s, t61sres)); + } + + var VideotexStringRestricted vts, vtsres; + + vts := "ttxx"; + os := enc_VideotexStringRestricted(vts); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + vtsres := dec_VideotexStringRestricted(os); + if (vts != vtsres) { + setverdict(fail, "tc_charstrings: ", match(vts, vtsres)); + } + + vts := ".:'" & char(2,5,64,42); + os := enc_VideotexStringRestricted(vts); + if (os != '082E3A27FA819480AA'O) { + setverdict(fail, "tc_universal_charstring: ", match('082E3A27FA819480AA'O, os)); + } + vtsres := dec_VideotexStringRestricted(os); + if (vts != vtsres) { + setverdict(fail, "tc_charstrings: ", match(vts, vtsres)); + } + + var GraphicStringRestricted gts, gtsres; + + gts := "ttxx"; + os := enc_GraphicStringRestricted(gts); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + gtsres := dec_GraphicStringRestricted(os); + if (gts != gsres) { + setverdict(fail, "tc_charstrings: ", match(gts, gtsres)); + } + + gts := ".:'" & char(2,5,64,42); + os := enc_GraphicStringRestricted(gts); + if (os != '082E3A27FA819480AA'O) { + setverdict(fail, "tc_universal_charstring: ", match('082E3A27FA819480AA'O, os)); + } + gtsres := dec_GraphicStringRestricted(os); + if (gts != gtsres) { + setverdict(fail, "tc_charstrings: ", match(gts, gtsres)); + } + + var GeneralStringRestricted gets, getsres; + + gets := "ttxx"; + os := enc_GeneralStringRestricted(gets); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + getsres := dec_GeneralStringRestricted(os); + if (gets != gesres) { + setverdict(fail, "tc_charstrings: ", match(gets, getsres)); + } + + gets := ".:'" & char(2,5,64,42); + os := enc_GeneralStringRestricted(gets); + if (os != '082E3A27FA819480AA'O) { + setverdict(fail, "tc_universal_charstring: ", match('082E3A27FA819480AA'O, os)); + } + getsres := dec_GeneralStringRestricted(os); + if (gets != getsres) { + setverdict(fail, "tc_charstrings: ", match(gets, getsres)); + }*/ + + + var BMPStringUnrestricted bs2, bs2res; + + bs2 := "abcd"; + os := enc_BMPStringUnrestricted(bs2); + if (os != '080061006200630064'O) { + setverdict(fail, "tc_universal_charstring: ", match('080061006200630064'O, os)); + } + bs2res := dec_BMPStringUnrestricted(os); + if (bs2 != bs2res) { + setverdict(fail, "tc_universal_charstring: ", match(bs2, bs2res)); + } + + bs2 := ".:'" & char(0,0,64,42); + os := enc_BMPStringUnrestricted(bs2); + if (os != '08002E003A0027402A'O) { + setverdict(fail, "tc_universal_charstring: ", match('08002E003A0027402A'O, os)); + } + bs2res := dec_BMPStringUnrestricted(os); + if (bs2 != bs2res) { + setverdict(fail, "tc_universal_charstring: ", match(bs2, bs2res)); + } + + var UniversalStringUnrestricted us2, us2res; + + us2 := "abcd"; + os := enc_UniversalStringUnrestricted(us2); + if (os != '1000000061000000620000006300000064'O) { + setverdict(fail, "tc_universal_charstring: ", match('1000000061000000620000006300000064'O, os)); + } + us2res := dec_UniversalStringUnrestricted(os); + if (us2 != us2res) { + setverdict(fail, "tc_universal_charstring: ", match(us2, us2res)); + } + + us2 := ".:'" & char(2,5,64,42); + os := enc_UniversalStringUnrestricted(us2); + if (os != '100000002E0000003A000000270205402A'O) { + setverdict(fail, "tc_universal_charstring: ", match('100000002E0000003A000000270205402A'O, os)); + } + us2res := dec_UniversalStringUnrestricted(os); + if (us2 != us2res) { + setverdict(fail, "tc_universal_charstring: ", match(us2, us2res)); + } + + var UTF8StringUnrestricted uts2, uts2res; + + uts2 := "abcd"; + os := enc_UTF8StringUnrestricted(uts2); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + uts2res := dec_UTF8StringUnrestricted(os); + if (uts2 != uts2res) { + setverdict(fail, "tc_universal_charstring: ", match(uts2, uts2res)); + } + + uts2 := ".:'" & char(2,5,64,42); + os := enc_UTF8StringUnrestricted(uts2); + if (os != '082E3A27FA819480AA'O) { + setverdict(fail, "tc_universal_charstring: ", match('082E3A27FA819480AA'O, os)); + } + uts2res := dec_UTF8StringUnrestricted(os); + if (uts2 != uts2res) { + setverdict(fail, "tc_universal_charstring: ", match(uts2, uts2res)); + } + + var TeletexStringUnrestricted ts2, ts2res; + + ts2 := "abcd"; + os := enc_TeletexStringUnrestricted(ts2); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + ts2res := dec_TeletexStringUnrestricted(os); + if (ts2 != ts2res) { + setverdict(fail, "tc_universal_charstring: ", match(ts2, ts2res)); + } + + ts2 := ".:'*"; + os := enc_TeletexStringUnrestricted(ts2); + if (os != '042E3A272A'O) { + setverdict(fail, "tc_universal_charstring: ", match('042E3A272A'O, os)); + } + ts2res := dec_TeletexStringUnrestricted(os); + if (ts2 != ts2res) { + setverdict(fail, "tc_universal_charstring: ", match(ts2, ts2res)); + } + + var T61StringUnrestricted t61s2, t61s2res; + + t61s2 := "abcd"; + os := enc_T61StringUnrestricted(t61s2); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + t61s2res := dec_T61StringUnrestricted(os); + if (t61s2 != t61s2res) { + setverdict(fail, "tc_universal_charstring: ", match(t61s2, t61s2res)); + } + + t61s2 := ".:'*"; + os := enc_T61StringUnrestricted(t61s2); + if (os != '042E3A272A'O) { + setverdict(fail, "tc_universal_charstring: ", match('042E3A272A'O, os)); + } + t61s2res := dec_T61StringUnrestricted(os); + if (t61s2 != t61s2res) { + setverdict(fail, "tc_universal_charstring: ", match(t61s2, t61s2res)); + } + + var VideotexStringUnrestricted vts2, vts2res; + + vts2 := "abcd"; + os := enc_VideotexStringUnrestricted(vts2); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + vts2res := dec_VideotexStringUnrestricted(os); + if (vts2 != vts2res) { + setverdict(fail, "tc_universal_charstring: ", match(vts2, vts2res)); + } + + vts2 := ".:'*"; + os := enc_VideotexStringUnrestricted(vts2); + if (os != '042E3A272A'O) { + setverdict(fail, "tc_universal_charstring: ", match('042E3A272A'O, os)); + } + vts2res := dec_VideotexStringUnrestricted(os); + if (vts2 != vts2res) { + setverdict(fail, "tc_universal_charstring: ", match(vts2, vts2res)); + } + + var GraphicStringUnrestricted gts2, gts2res; + + gts2 := "abcd"; + os := enc_GraphicStringUnrestricted(gts2); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + gts2res := dec_GraphicStringUnrestricted(os); + if (gts2 != gts2res) { + setverdict(fail, "tc_universal_charstring: ", match(gts2, gts2res)); + } + + gts2 := ".:'*"; + os := enc_GraphicStringUnrestricted(gts2); + if (os != '042E3A272A'O) { + setverdict(fail, "tc_universal_charstring: ", match('042E3A272A'O, os)); + } + gts2res := dec_GraphicStringUnrestricted(os); + if (gts2 != gts2res) { + setverdict(fail, "tc_universal_charstring: ", match(gts2, gts2res)); + } + + var GeneralStringUnrestricted gets2, gets2res; + + gets2 := "abcd"; + os := enc_GeneralStringUnrestricted(gets2); + if (os != '0461626364'O) { + setverdict(fail, "tc_universal_charstring: ", match('0461626364'O, os)); + } + gets2res := dec_GeneralStringUnrestricted(os); + if (gets2 != gets2res) { + setverdict(fail, "tc_universal_charstring: ", match(gets2, gets2res)); + } + + gets2 := ".:'*"; + os := enc_GeneralStringUnrestricted(gets2); + if (os != '042E3A272A'O) { + setverdict(fail, "tc_universal_charstring: ", match('042E3A272A'O, os)); + } + gets2res := dec_GeneralStringUnrestricted(os); + if (gets2 != gets2res) { + setverdict(fail, "tc_universal_charstring: ", match(gets2, gets2res)); + } + + + setverdict(pass); + + } + + external function enc_OBJID(in OBJID pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_OBJID(in octetstring stream) return OBJID + with { extension "prototype (convert) decode(OER)" } + + external function enc_ROBJID(in ROBJID pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ROBJID(in octetstring stream) return ROBJID + with { extension "prototype (convert) decode(OER)" } + + testcase tc_objid() runs on EmptyCT { + var OBJID oid, oidres; + var octetstring os; + + oid := objid{1 2 3 4 5 6}; + os := enc_OBJID(oid); + if (os != '052A03040506'O) { + setverdict(fail, "tc_objid: ", match('052A03040506'O, os)); + } + oidres := dec_OBJID(os); + if (oid != oidres) { + setverdict(fail, "tc_charstrings: ", match(oid, oidres)); + } + + oid := objid{1 35 994 431 5 1}; + os := enc_OBJID(oid); + if (os != '074B8762832F0501'O) { + setverdict(fail, "tc_objid: ", match('074B8762832F0501'O, os)); + } + oidres := dec_OBJID(os); + if (oid != oidres) { + setverdict(fail, "tc_charstrings: ", match(oid, oidres)); + } + + var ROBJID roid, roidres; + + roid := myROBJID; + os := enc_ROBJID(roid); + if (os != '06010203040506'O) { + setverdict(fail, "tc_objid: ", match('06010203040506'O, os)); + } + roidres := dec_ROBJID(os); + if (roid != roidres) { + setverdict(fail, "tc_charstrings: ", match(roid, roidres)); + } + + roid := myROBJID2; + os := enc_ROBJID(roid); + if (os != '0801238762832F0501'O) { + setverdict(fail, "tc_objid: ", match('0801238762832F0501'O, os)); + } + roidres := dec_ROBJID(os); + if (roid != roidres) { + setverdict(fail, "tc_charstrings: ", match(roid, roidres)); + } + + setverdict(pass); + } + + external function enc_MyPDV(in MyPDV pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_MyPDV(in octetstring stream) return MyPDV + with { extension "prototype (convert) decode(OER)" } + + testcase tc_pdv() runs on EmptyCT { + var MyPDV pdv, pdvres; + var octetstring os; + + pdv := { + identification := { + syntaxes := { + abstract := objid{1 2 3}, + transfer := objid{1 5 6} + } + }, + data_value := '12345678'O + }; + os := enc_MyPDV(pdv); + if (os != '80022A03022D060412345678'O) { + setverdict(fail, "tc_pdv: ", match('80022A03022D060412345678'O, os)); + } + pdvres := dec_MyPDV(os); + if (pdv != pdvres) { + setverdict(fail, "tc_pdv: ", match(pdv, pdvres)); + } + + pdv := { + identification := { + syntax := objid{1 2 3} + }, + data_value := '12345678'O + }; + os := enc_MyPDV(pdv); + if (os != '81022A030412345678'O) { + setverdict(fail, "tc_pdv: ", match('81022A030412345678'O, os)); + } + pdvres := dec_MyPDV(os); + if (pdv != pdvres) { + setverdict(fail, "tc_pdv: ", match(pdv, pdvres)); + } + + pdv := { + identification := { + presentation_context_id := 414 + }, + data_value := '12345678'O + }; + os := enc_MyPDV(pdv); + if (os != '8202019E0412345678'O) { + setverdict(fail, "tc_pdv: ", match('8202019E0412345678'O, os)); + } + pdvres := dec_MyPDV(os); + if (pdv != pdvres) { + setverdict(fail, "tc_pdv: ", match(pdv, pdvres)); + } + + pdv := { + identification := { + context_negotiation := { + presentation_context_id := 414, + transfer_syntax := objid{1 2 3} + } + }, + data_value := '12345678'O + }; + os := enc_MyPDV(pdv); + if (os != '8302019E022A030412345678'O) { + setverdict(fail, "tc_pdv: ", match('8302019E022A030412345678'O, os)); + } + pdvres := dec_MyPDV(os); + if (pdv != pdvres) { + setverdict(fail, "tc_pdv: ", match(pdv, pdvres)); + } + + pdv := { + identification := { + transfer_syntax := objid{1 2 3} + }, + data_value := '12345678'O + }; + os := enc_MyPDV(pdv); + if (os != '84022A030412345678'O) { + setverdict(fail, "tc_pdv: ", match('84022A030412345678'O, os)); + } + pdvres := dec_MyPDV(os); + if (pdv != pdvres) { + setverdict(fail, "tc_pdv: ", match(pdv, pdvres)); + } + + pdv := { + identification := { + fixed := NULL + }, + data_value := '12345678'O + }; + os := enc_MyPDV(pdv); + if (os != '850412345678'O) { + setverdict(fail, "tc_pdv: ", match('850412345678'O, os)); + } + pdvres := dec_MyPDV(os); + if (pdv != pdvres) { + setverdict(fail, "tc_pdv: ", match(pdv, pdvres)); + } + + setverdict(pass); + } + + external function enc_Union(in Union pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_Union(in octetstring stream) return Union + with { extension "prototype (convert) decode(OER)" } + + testcase tc_union() runs on EmptyCT { + var Union u, ures; + var octetstring os; + + u := { + f1 := 1 + } + os := enc_Union(u); + if (os != '7F400101'O) { + setverdict(fail, "tc_union: ", match('7F400101'O, os)); + } + ures := dec_Union(os); + if (u != ures) { + setverdict(fail, "tc_union: ", match(u, ures)); + } + + u := { + f2 := 1 + } + os := enc_Union(u); + if (os != '7F3F0101'O) { + setverdict(fail, "tc_union: ", match('7F3F0101'O, os)); + } + ures := dec_Union(os); + if (u != ures) { + setverdict(fail, "tc_union: ", match(u, ures)); + } + + u := { + f3 := 1 + } + os := enc_Union(u); + if (os != '7E0101'O) { + setverdict(fail, "tc_union: ", match('7E0101'O, os)); + } + ures := dec_Union(os); + if (u != ures) { + setverdict(fail, "tc_union: ", match(u, ures)); + } + + u := { + f4 := 1 + } + os := enc_Union(u); + if (os != '7FFF7F0101'O) { + setverdict(fail, "tc_union: ", match('7FFF7F0101'O, os)); + } + ures := dec_Union(os); + if (u != ures) { + setverdict(fail, "tc_union: ", match(u, ures)); + } + + u := { + f5 := 1 + } + os := enc_Union(u); + if (os != '020101'O) { + setverdict(fail, "tc_union: ", match('020101'O, os)); + } + ures := dec_Union(os); + if (u != ures) { + setverdict(fail, "tc_union: ", match(u, ures)); + } + + u := { + f6 := 1 + } + os := enc_Union(u); + if (os != 'FF82450101'O) { + setverdict(fail, "tc_union: ", match('FF82450101'O, os)); + } + ures := dec_Union(os); + if (u != ures) { + setverdict(fail, "tc_union: ", match(u, ures)); + } + + u := { + f7 := 1 + } + os := enc_Union(u); + if (os != 'FFBB2C0101'O) { + setverdict(fail, "tc_union: ", match('FFBB2C0101'O, os)); + } + ures := dec_Union(os); + if (u != ures) { + setverdict(fail, "tc_union: ", match(u, ures)); + } + + u := { + f8 := 1 + } + os := enc_Union(u); + if (os != 'D20101'O) { + setverdict(fail, "tc_union: ", match('D20101'O, os)); + } + ures := dec_Union(os); + if (u != ures) { + setverdict(fail, "tc_union: ", match(u, ures)); + } + + u := { + f9 := 1 + } + os := enc_Union(u); + if (os != 'C301'O) { + setverdict(fail, "tc_union: ", match('C301'O, os)); + } + ures := dec_Union(os); + if (u != ures) { + setverdict(fail, "tc_union: ", match(u, ures)); + } + + setverdict(pass); + } + + external function enc_EmptyRecord(in EmptyRecord pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_EmptyRecord(in octetstring stream) return EmptyRecord + with { extension "prototype (convert) decode(OER)" } + + external function enc_ExtensionRecord(in ExtensionRecord pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ExtensionRecord(in octetstring stream) return ExtensionRecord + with { extension "prototype (convert) decode(OER)" } + + external function enc_NoOptionalRecord(in NoOptionalRecord pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_NoOptionalRecord(in octetstring stream) return NoOptionalRecord + with { extension "prototype (convert) decode(OER)" } + + external function enc_OptionalRecord(in OptionalRecord pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_OptionalRecord(in octetstring stream) return OptionalRecord + with { extension "prototype (convert) decode(OER)" } + + external function enc_SomeOptionalRecord(in SomeOptionalRecord pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_SomeOptionalRecord(in octetstring stream) return SomeOptionalRecord + with { extension "prototype (convert) decode(OER)" } + + testcase tc_sequence() runs on EmptyCT { + var octetstring os; + + var EmptyRecord emr, emrres; + emr := { } + os := enc_EmptyRecord(emr); + if (os != ''O) { + setverdict(fail, "tc_sequence: ", match(''O, os)); + } + emrres := dec_EmptyRecord(os); + if (emr != emrres) { + setverdict(fail, "tc_sequence: ", match(emr, emrres)); + } + + // Test extension bit presence, FAILS, possibly some bug with is_extendable() function + /*var ExtensionRecord er, erres; + er := { me := e2 } + os := enc_ExtensionRecord(er); + if (os != '0001'O) { + setverdict(fail, "tc_sequence: ", match('0001'O, os)); + } + erres := dec_ExtensionRecord(os); + if (er != erres) { + setverdict(fail, "tc_sequence: ", match(er, erres)); + }*/ + + var NoOptionalRecord nr, nrres; + + nr := { + ub := 4536366262, + u1b := 111, + u1b2 := 66, + s1b := -85, + s1b2 := -21, + u2b := 32596, + s2b := -17639, + u4b := 56464631, + s4b := -1331326, + u8b := 4946464979873, + s8b := -4164613213, + me := ebig, + bsr := '10101111'B, + bsr2 := '101111101'B, + bsr3 := '010'B, + bsu := '10101110101010110'B, + osr := 'ABCD1234'O, + osu := '131314676886BDBADA'O, + ru := 42343242.4352, + rr := 4321431.511, + nullt := NULL, + iasr := "sags", + isor := "gdgg", + vsr := "aanb", + nsr := "1697", + psr := "abfd", + ias := "gdsgdsgdsgdhhfgjhfd", + iso := "454325f46gssf", + vs := "gdfhgdshgdshgdr7u", + ns := "697365463", + ps := "435346gf", + /*bmpr := char(0,0,54,63) & "abf", + usr := char(0,0,54,63) & "abf", + utfr := char(0,0,54,63) & "abf", + tsr := char(0,0,54,63) & "abf", + t61sr := char(0,0,54,63) & "abf", + visr := char(0,0,54,63) & "abf", + gsr := char(0,0,54,63) & "abf", + gesr := char(0,0,54,63) & "abf",*/ + bmpu := char(0,0,54,63) & "abf", + usu := char(0,0,54,63) & "abfsdfa" , + uftu := char(0,0,54,63) & "abfsdfa", + tsu := "abfsdfa" , + t61u := "abfsdfa" , + vsu := "abfsdfa" , + gsu := "abfsdfa" , + gesu := "abfsdfa" + //ob := objid{1 16 63 1 6 76}, + //rob := myROBJID + } + os := enc_NoOptionalRecord(nr); + if (os != '05010E6374B66F42ABEB7F54BB19035D94F7FFEBAF820000047FB049BBA1FFFFFFFF07C50BA38407D3CDE9AFBE80400407AEAB00ABCD123409131314676886BDBADA11033432333433323432343335322E452D340F03343332313433313531312E452D33736167736764676761616E623136393761626664136764736764736764736764686866676A6866640D343534333235663436677373661167646668676473686764736867647237750936393733363534363308343335333436676608363F006100620066200000363F000000610000006200000066000000730000006400000066000000610AE398BF6162667364666107616266736466610761626673646661076162667364666107616266736466610761626673646661'O) { + setverdict(fail, "tc_sequence: ", match('05010E6374B66F42ABEB7F54BB19035D94F7FFEBAF820000047FB049BBA1FFFFFFFF07C50BA38407D3CDE9AFBE80400407AEAB00ABCD123409131314676886BDBADA11033432333433323432343335322E452D340F03343332313433313531312E452D33736167736764676761616E623136393761626664136764736764736764736764686866676A6866640D343534333235663436677373661167646668676473686764736867647237750936393733363534363308343335333436676608363F006100620066200000363F000000610000006200000066000000730000006400000066000000610AE398BF6162667364666107616266736466610761626673646661076162667364666107616266736466610761626673646661'O, os)); + } + nrres := dec_NoOptionalRecord(os); + if (nr != nrres) { + setverdict(fail, "tc_sequence: ", match(nr, nrres)); + } + + + var OptionalRecord onr, onrres; + + onr := { + ub := 4536366262, + u1b := omit, + u1b2 := 66, + s1b := -85, + s1b2 := -21, + u2b := 32596, + s2b := -17639, + u4b := 56464631, + s4b := -1331326, + u8b := 4946464979873, + s8b := -4164613213, + me := ebig, + bsr := '10101111'B, + bsr2 := '101111101'B, + bsr3 := '010'B, + bsu := '10101110101010110'B, + osr := 'ABCD1234'O, + osu := '131314676886BDBADA'O, + ru := 42343242.4352, + rr := 4321431.511, + nullt := NULL, + iasr := "sags", + isor := "gdgg", + vsr := "aanb", + nsr := "1697", + psr := "abfd", + ias := "gdsgdsgdsgdhhfgjhfd", + iso := "454325f46gssf", + vs := "gdfhgdshgdshgdr7u", + ns := "697365463", + ps := "435346gf", + /*bmpr := char(0,0,54,63) & "abf", + usr := char(0,0,54,63) & "abf", + utfr := char(0,0,54,63) & "abf", + tsr := char(0,0,54,63) & "abf", + t61sr := char(0,0,54,63) & "abf", + visr := char(0,0,54,63) & "abf", + gsr := char(0,0,54,63) & "abf", + gesr := char(0,0,54,63) & "abf",*/ + bmpu := char(0,0,54,63) & "abf", + usu := char(0,0,54,63) & "abfsdfa" , + uftu := char(0,0,54,63) & "abfsdfa", + tsu := "abfsdfa" , + t61u := "abfsdfa" , + vsu := "abfsdfa" , + gsu := "abfsdfa" , + gesu := "abfsdfa" + //ob := objid{1 16 63 1 6 76}, + //rob := myROBJID + } + os := enc_OptionalRecord(onr); + if (os != 'BFFFFFFFFE05010E6374B642ABEB7F54BB19035D94F7FFEBAF820000047FB049BBA1FFFFFFFF07C50BA38407D3CDE9AFBE80400407AEAB00ABCD123409131314676886BDBADA11033432333433323432343335322E452D340F03343332313433313531312E452D33736167736764676761616E623136393761626664136764736764736764736764686866676A6866640D343534333235663436677373661167646668676473686764736867647237750936393733363534363308343335333436676608363F006100620066200000363F000000610000006200000066000000730000006400000066000000610AE398BF6162667364666107616266736466610761626673646661076162667364666107616266736466610761626673646661'O) { + setverdict(fail, "tc_sequence: ", match('BFFFFFFFFE05010E6374B642ABEB7F54BB19035D94F7FFEBAF820000047FB049BBA1FFFFFFFF07C50BA38407D3CDE9AFBE80400407AEAB00ABCD123409131314676886BDBADA11033432333433323432343335322E452D340F03343332313433313531312E452D33736167736764676761616E623136393761626664136764736764736764736764686866676A6866640D343534333235663436677373661167646668676473686764736867647237750936393733363534363308343335333436676608363F006100620066200000363F000000610000006200000066000000730000006400000066000000610AE398BF6162667364666107616266736466610761626673646661076162667364666107616266736466610761626673646661'O, os)); + } + onrres := dec_OptionalRecord(os); + if (onr != onrres) { + setverdict(fail, "tc_sequence: ", match(onr, onrres)); + } + + onr := { + ub := 4536366262, + u1b := omit, + u1b2 := 66, + s1b := -85, + s1b2 := -21, + u2b := 32596, + s2b := -17639, + u4b := 56464631, + s4b := -1331326, + u8b := 4946464979873, + s8b := -4164613213, + me := esmall, + bsr := omit, + bsr2 := '101111101'B, + bsr3 := '010'B, + bsu := '10101110101010110'B, + osr := 'ABCD1234'O, + osu := '131314676886BDBADA'O, + ru := 42343242.4352, + rr := 4321431.511, + nullt := NULL, + iasr := "sags", + isor := omit, + vsr := "aanb", + nsr := "1697", + psr := "abfd", + ias := "gdsgdsgdsgdhhfgjhfd", + iso := omit, + vs := omit, + ns := omit, + ps := "435346gf", + /*bmpr := char(0,0,54,63) & "abf", + usr := char(0,0,54,63) & "abf", + utfr := char(0,0,54,63) & "abf", + tsr := char(0,0,54,63) & "abf", + t61sr := char(0,0,54,63) & "abf", + visr := char(0,0,54,63) & "abf", + gsr := char(0,0,54,63) & "abf", + gesr := char(0,0,54,63) & "abf",*/ + bmpu := char(0,0,54,63) & "abf", + usu := char(0,0,54,63) & "abfsdfa" , + uftu := omit, + tsu := "abfsdfa" , + t61u := "abfsdfa" , + vsu := "abfsdfa" , + gsu := "abfsdfa" , + gesu := "abfsdfa" + //ob := objid{1 16 63 1 6 76}, + //rob := myROBJID + } + os := enc_OptionalRecord(onr); + if (os != 'BFF7FDE3BE05010E6374B642ABEB7F54BB19035D94F7FFEBAF820000047FB049BBA1FFFFFFFF07C50BA384FEB8D1B4BE80400407AEAB00ABCD123409131314676886BDBADA11033432333433323432343335322E452D340F03343332313433313531312E452D337361677361616E623136393761626664136764736764736764736764686866676A68666408343335333436676608363F006100620066200000363F0000006100000062000000660000007300000064000000660000006107616266736466610761626673646661076162667364666107616266736466610761626673646661'O) { + setverdict(fail, "tc_sequence: ", match('BFF7FDE3BE05010E6374B642ABEB7F54BB19035D94F7FFEBAF820000047FB049BBA1FFFFFFFF07C50BA384FEB8D1B4BE80400407AEAB00ABCD123409131314676886BDBADA11033432333433323432343335322E452D340F03343332313433313531312E452D337361677361616E623136393761626664136764736764736764736764686866676A68666408343335333436676608363F006100620066200000363F0000006100000062000000660000007300000064000000660000006107616266736466610761626673646661076162667364666107616266736466610761626673646661'O, os)); + } + onrres := dec_OptionalRecord(os); + if (onr != onrres) { + setverdict(fail, "tc_sequence: ", match(onr, onrres)); + } + + + onr := { + ub := omit, + u1b := omit, + u1b2 := omit, + s1b := omit, + s1b2 := omit, + u2b := omit, + s2b := omit, + u4b := omit, + s4b := omit, + u8b := omit, + s8b := omit, + me := omit, + bsr := omit, + bsr2 := omit, + bsr3 := omit, + bsu := omit, + osr := omit, + osu := omit, + ru := omit, + rr := omit, + nullt := omit, + iasr := omit, + isor := omit, + vsr := omit, + nsr := omit, + psr := omit, + ias := omit, + iso := omit, + vs := omit, + ns := omit, + ps := omit, + /*bmpr := char(0,0,54,63) & "abf", + usr := char(0,0,54,63) & "abf", + utfr := char(0,0,54,63) & "abf", + tsr := char(0,0,54,63) & "abf", + t61sr := char(0,0,54,63) & "abf", + visr := char(0,0,54,63) & "abf", + gsr := char(0,0,54,63) & "abf", + gesr := char(0,0,54,63) & "abf",*/ + bmpu := omit, + usu := omit, + uftu := omit, + tsu := omit, + t61u := omit, + vsu := omit, + gsu := omit, + gesu := omit + //ob := objid{1 16 63 1 6 76}, + //rob := myROBJID + } + os := enc_OptionalRecord(onr); + if (os != '0000000000'O) { + setverdict(fail, "tc_sequence: ", match('0000000000'O, os)); + } + onrres := dec_OptionalRecord(os); + if (onr != onrres) { + setverdict(fail, "tc_sequence: ", match(onr, onrres)); + } + + var SomeOptionalRecord sor, sorres; + sor := { + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9 + } + os := enc_SomeOptionalRecord(sor); + if (os != 'FC0100010101020103010401050106010701080109'O) { + setverdict(fail, "tc_sequence: ", match('FC0100010101020103010401050106010701080109'O, os)); + } + sorres := dec_SomeOptionalRecord(os); + if (sor != sorres) { + setverdict(fail, "tc_sequence: ", match(sor, sorres)); + } + + sor := { + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := omit, + f5 := omit, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9 + } + os := enc_SomeOptionalRecord(sor); + if (os != 'CC01000101010201030106010701080109'O) { + setverdict(fail, "tc_sequence: ", match('CC01000101010201030106010701080109'O, os)); + } + sorres := dec_SomeOptionalRecord(os); + if (sor != sorres) { + setverdict(fail, "tc_sequence: ", match(sor, sorres)); + } + + sor := { + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := omit, + f5 := omit, + f6 := 6, + f7 := omit, + f8 := 8, + f9 := 9 + } + os := enc_SomeOptionalRecord(sor); + if (os != '84010001010103010601080109'O) { + setverdict(fail, "tc_sequence: ", match('84010001010103010601080109'O, os)); + } + sorres := dec_SomeOptionalRecord(os); + if (sor != sorres) { + setverdict(fail, "tc_sequence: ", match(sor, sorres)); + } + + + setverdict(pass); + } + + external function enc_MySet(in MySet pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_MySet(in octetstring stream) return MySet + with { extension "prototype (convert) decode(OER)" } + + testcase tc_set() runs on EmptyCT { + var MySet ms, msres; + var octetstring os; + + ms := { + r1 := 3.14, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6 + } + os := enc_MySet(ms); + if (os != '800102010401030106010508033331342E452D320101'O) { + setverdict(fail, "tc_set: ", match('800102010401030106010508033331342E452D320101'O, os)); + } + msres := dec_MySet(os); + if (ms != msres) { + setverdict(fail, "tc_set: ", match(ms, msres)); + } + + setverdict(pass); + } + + external function enc_MyRecordOf(in MyRecordOf pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_MyRecordOf(in octetstring stream) return MyRecordOf + with { extension "prototype (convert) decode(OER)" } + + external function enc_MySetOf(in MySetOf pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_MySetOf(in octetstring stream) return MySetOf + with { extension "prototype (convert) decode(OER)" } + + external function enc_ROI(in ROI pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ROI(in octetstring stream) return ROI + with { extension "prototype (convert) decode(OER)" } + + testcase tc_recordof() runs on EmptyCT { + var MyRecordOf ro, rores; + var octetstring os; + + ro := { + { + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := omit, + f5 := omit, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9 + }, + { + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := omit, + f5 := omit, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9 + } + } + os := enc_MyRecordOf(ro); + if (os != '0102CC01000101010201030106010701080109CC01000101010201030106010701080109'O) { + setverdict(fail, "tc_recordof: ", match('0102CC01000101010201030106010701080109CC01000101010201030106010701080109'O, os)); + } + rores := dec_MyRecordOf(os); + if (ro != rores) { + setverdict(fail, "tc_recordof: ", match(ro, rores)); + } + + var MySetOf so, sores; + + so := { + { + r1 := 3.14, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6 + }, + { + r1 := 3.14, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6 + } + } + os := enc_MySetOf(so); + if (os != '0102800102010401030106010508033331342E452D320101800102010401030106010508033331342E452D320101'O) { + setverdict(fail, "tc_recordof: ", match('0102800102010401030106010508033331342E452D320101800102010401030106010508033331342E452D320101'O, os)); + } + sores := dec_MySetOf(os); + if (so != sores) { + setverdict(fail, "tc_recordof: ", match(so, sores)); + } + + var ROI roi, roires; + + roi := {1,2,3,4} + os := enc_ROI(roi); + if (os != '010401020304'O) { + setverdict(fail, "tc_recordof: ", match('010401020304'O, os)); + } + roires := dec_ROI(os); + if (roi != roires) { + setverdict(fail, "tc_recordof: ", match(roi, roires)); + } + + os := '010401020304'O; + roires := dec_ROI(os); + if (roi != roires) { + setverdict(fail, "tc_recordof: ", match(roi, roires)); + } + + setverdict(pass); + } + + external function enc_MyExternal(in MyExternal pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_MyExternal(in octetstring stream) return MyExternal + with { extension "prototype (convert) decode(OER)" } + + testcase tc_external() runs on EmptyCT { + var MyExternal ex, exres; + var octetstring os; + + ex := { + identification := { + syntax := objid{1 2 3} + }, + data_value_descriptor := omit, + data_value := '12345678'O + }; + os := enc_MyExternal(ex); + if (os != '80022A03810412345678'O) { + setverdict(fail, "tc_external: ", match('80022A03810412345678'O, os)); + } + exres := dec_MyExternal(os); + if (ex != exres) { + setverdict(fail, "tc_external: ", match(ex, exres)); + } + + ex := { + identification := { + presentation_context_id := 7934 + }, + data_value_descriptor := "something", + data_value := '12345678'O + }; + os := enc_MyExternal(ex); + if (os != '60021EFE09736F6D657468696E67810412345678'O) { + setverdict(fail, "tc_external: ", match('60021EFE09736F6D657468696E67810412345678'O, os)); + } + exres := dec_MyExternal(os); + if (ex != exres) { + setverdict(fail, "tc_external: ", match(ex, exres)); + } + + ex := { + identification := { + context_negotiation := { + presentation_context_id := 414, + transfer_syntax := objid{1 2 3} + } + }, + data_value_descriptor := "something", + data_value := '12345678'O + }; + os := enc_MyExternal(ex); + if (os != 'E0022A0302019E09736F6D657468696E67810412345678'O) { + setverdict(fail, "tc_external: ", match('E0022A0302019E09736F6D657468696E67810412345678'O, os)); + } + exres := dec_MyExternal(os); + if (ex != exres) { + setverdict(fail, "tc_external: ", match(ex, exres)); + } + + + + setverdict(pass); + } + + external function enc_Item(in Item pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_Item(in octetstring stream) return Item + with { extension "prototype (convert) decode(OER)" } + + testcase tc_opentype() runs on EmptyCT { + var Item pf, pfres; + var octetstring os; + + pf := { + otherFeature := {subItem := {itemCode := 109, otherFeature := {Weight := "54" }} }, + itemCode := 104, + itemDescription := "Bookshelf", + feature := {Weight := "24"}, + isTaxable := false + }; + os := enc_Item(pf); + if (os != '080000006D030235340000006809426F6F6B7368656C660302323400'O) { + setverdict(fail, "tc_opentype: ", match('080000006D030235340000006809426F6F6B7368656C660302323400'O, os)); + } + pfres := dec_Item(os); + if (pf != pfres) { + setverdict(fail, "tc_opentype: ", match(pf, pfres)); + } + + setverdict(pass); + } + + external function enc_PersonnelRecord(in PersonnelRecord pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_PersonnelRecord(in octetstring stream) return PersonnelRecord + with { extension "prototype (convert) decode(OER)" } + + testcase tc_example() runs on EmptyCT { + var PersonnelRecord prres; + var octetstring os; + + os := enc_PersonnelRecord(johny); + if (os != '80044A6F686E015005536D6974680133084469726563746F72083139373130393137044D617279015405536D69746801020552616C7068015405536D69746808313935373131313105537573616E0142054A6F6E6573083139353930373137'O) { + setverdict(fail, "tc_example: ", match('80044A6F686E015005536D6974680133084469726563746F72083139373130393137044D617279015405536D69746801020552616C7068015405536D69746808313935373131313105537573616E0142054A6F6E6573083139353930373137'O, os)); + } + prres := dec_PersonnelRecord(os); + if (johny != prres) { + setverdict(fail, "tc_example: ", match(johny, prres)); + } setverdict(pass); @@ -748,5 +2804,21 @@ control { execute(tc_boolean()); execute(tc_integer()); + execute(tc_enumerated()); + execute(tc_bitstring()); + execute(tc_octetstring()); + execute(tc_float()); + execute(tc_null()); + execute(tc_charstrings()); + execute(tc_universal_charstring()); + execute(tc_objid()); + execute(tc_sequence()); + execute(tc_pdv()); + execute(tc_union()); + execute(tc_set()); + execute(tc_recordof()); + execute(tc_external()); + execute(tc_opentype()); + execute(tc_example()); } } \ No newline at end of file diff --git a/regression_test/OER/Types.asn b/regression_test/OER/Types.asn index 1100ad6e1733421f4fdfeb37a5236f0e8788eae3..21b63c4ce87ef9e0e4666c3bcb09b054294ccb37 100644 --- a/regression_test/OER/Types.asn +++ b/regression_test/OER/Types.asn @@ -10,13 +10,12 @@ -- --///////////////////////////////////////////////////////////////////////////// Types -DEFINITIONS +DEFINITIONS AUTOMATIC TAGS - +EXTENSIBILITY IMPLIED ::= - -BEGIN + BEGIN IMPORTS ; -- nothing @@ -44,4 +43,332 @@ Unsigned8byteInt ::= INTEGER (0..18446744073709551615) Signed8byteInt ::= INTEGER (-9223372036854775808..9223372036854775807) +MyEnum ::= ENUMERATED +{ + e0 (0), + e1 (1), + e2 (2), + ebig (131321321), + esmall (-21442124) +} + +BitstringRestricted ::= BIT STRING (SIZE(8)) + +BitstringRestricted2 ::= BIT STRING (SIZE(9)) + +BitstringRestricted3 ::= BIT STRING (SIZE(3)) + +BitstringUnrestricted ::= BIT STRING + +OctetstringRestricted ::= OCTET STRING (SIZE(4)) + +OctetstringUnrestricted ::= OCTET STRING + +RealUnrestricted ::= REAL + +RealRestricted ::= REAL (0 | WITH COMPONENTS { mantissa (-99999..99999), base (1), exponent (-20..20)}) + +NullType ::= NULL + +IA5StringRestricted ::= IA5String (SIZE(4)) + +ISO646StringRestricted ::= ISO646String (SIZE(4)) + +VisibleStringRestricted ::= VisibleString (SIZE(4)) + +NumericStringRestricted ::= NumericString (SIZE(4)) + +PrintableStringRestricted ::= PrintableString (SIZE(4)) + +IA5StringUnrestricted ::= IA5String + +ISO646StringUnrestricted ::= ISO646String + +VisibleStringUnrestricted ::= VisibleString + +NumericStringUnrestricted ::= NumericString + +PrintableStringUnrestricted ::= PrintableString + +BMPStringRestricted ::= BMPString (SIZE(4)) + +UniversalStringRestricted ::= UniversalString (SIZE(4)) + +UTF8StringRestricted ::= UTF8String (SIZE(4)) + +TeletexStringRestricted ::= TeletexString (SIZE(4)) + +T61StringRestricted ::= T61String (SIZE(4)) + +VideotexStringRestricted ::= VideotexString (SIZE(4)) + +GraphicStringRestricted ::= GraphicString (SIZE(4)) + +GeneralStringRestricted ::= GeneralString (SIZE(4)) + +BMPStringUnrestricted ::= BMPString + +UniversalStringUnrestricted ::= UniversalString + +UTF8StringUnrestricted ::= UTF8String + +TeletexStringUnrestricted ::= TeletexString + +T61StringUnrestricted ::= T61String + +VideotexStringUnrestricted ::= VideotexString + +GraphicStringUnrestricted ::= GraphicString + +GeneralStringUnrestricted ::= GeneralString + +OBJID ::= OBJECT IDENTIFIER + +ROBJID ::= RELATIVE-OID + +myROBJID ROBJID ::= {1 2 3 4 5 6} + +myROBJID2 ROBJID ::= {1 35 994 431 5 1} + +--MyInt2 ::= INTEGER ( REAL(1.0..3.0) UNION PrintableString("abc") UNION INTEGER(1..10) ) + +NoOptionalRecord ::= SEQUENCE { + ub UnLimitedInt, + u1b Unsigned1byteInt, + u1b2 Unsigned1byteInt2, + s1b Signed1byteInt, + s1b2 Signed1byteInt2, + u2b Unsigned2byteInt, + s2b Signed2byteInt, + u4b Unsigned4byteInt, + s4b Signed4byteInt, + u8b Unsigned8byteInt, + s8b Signed8byteInt, + me MyEnum, + bsr BitstringRestricted, + bsr2 BitstringRestricted2, + bsr3 BitstringRestricted3, + bsu BitstringUnrestricted, + osr OctetstringRestricted, + osu OctetstringUnrestricted, + ru RealUnrestricted, + rr RealRestricted, + nullt NullType, + iasr IA5StringRestricted, + isor ISO646StringRestricted, + vsr VisibleStringRestricted, + nsr NumericStringRestricted, + psr PrintableStringRestricted, + ias IA5StringUnrestricted, + iso ISO646StringUnrestricted, + vs VisibleStringUnrestricted, + ns NumericStringUnrestricted, + ps PrintableStringUnrestricted, + --bmpr BMPStringRestricted, + --usr UniversalStringRestricted, + --utfr UTF8StringRestricted, + --tsr TeletexStringRestricted, + --t61sr T61StringRestricted, + --visr VideotexStringRestricted, + --gsr GraphicStringRestricted, + --gesr GeneralStringRestricted, + bmpu BMPStringUnrestricted, + usu UniversalStringUnrestricted, + uftu UTF8StringUnrestricted, + tsu TeletexStringUnrestricted, + t61u T61StringUnrestricted, + vsu VideotexStringUnrestricted, + gsu GraphicStringUnrestricted, + gesu GeneralStringUnrestricted + --ob OBJID, + --rob ROBJID +} + + +OptionalRecord ::= SEQUENCE { + ub UnLimitedInt OPTIONAL, + u1b Unsigned1byteInt OPTIONAL, + u1b2 Unsigned1byteInt2 OPTIONAL, + s1b Signed1byteInt OPTIONAL, + s1b2 Signed1byteInt2 OPTIONAL, + u2b Unsigned2byteInt OPTIONAL, + s2b Signed2byteInt OPTIONAL, + u4b Unsigned4byteInt OPTIONAL, + s4b Signed4byteInt OPTIONAL, + u8b Unsigned8byteInt OPTIONAL, + s8b Signed8byteInt OPTIONAL, + me MyEnum OPTIONAL, + bsr BitstringRestricted OPTIONAL, + bsr2 BitstringRestricted2 OPTIONAL, + bsr3 BitstringRestricted3 OPTIONAL, + bsu BitstringUnrestricted OPTIONAL, + osr OctetstringRestricted OPTIONAL, + osu OctetstringUnrestricted OPTIONAL, + ru RealUnrestricted OPTIONAL, + rr RealRestricted OPTIONAL, + nullt NullType OPTIONAL, + iasr IA5StringRestricted OPTIONAL, + isor ISO646StringRestricted OPTIONAL, + vsr VisibleStringRestricted OPTIONAL, + nsr NumericStringRestricted OPTIONAL, + psr PrintableStringRestricted OPTIONAL, + ias IA5StringUnrestricted OPTIONAL, + iso ISO646StringUnrestricted OPTIONAL, + vs VisibleStringUnrestricted OPTIONAL, + ns NumericStringUnrestricted OPTIONAL, + ps PrintableStringUnrestricted OPTIONAL, + --bmpr BMPStringRestricted, + --usr UniversalStringRestricted, + --utfr UTF8StringRestricted, + --tsr TeletexStringRestricted, + --t61sr T61StringRestricted, + --visr VideotexStringRestricted, + --gsr GraphicStringRestricted, + --gesr GeneralStringRestricted, + bmpu BMPStringUnrestricted OPTIONAL, + usu UniversalStringUnrestricted OPTIONAL, + uftu UTF8StringUnrestricted OPTIONAL, + tsu TeletexStringUnrestricted OPTIONAL, + t61u T61StringUnrestricted OPTIONAL, + vsu VideotexStringUnrestricted OPTIONAL, + gsu GraphicStringUnrestricted OPTIONAL, + gesu GeneralStringUnrestricted OPTIONAL + --ob OBJID, + --rob ROBJID +} + +ExtensionRecord ::= SEQUENCE { + me MyEnum, + ..., + f INTEGER +} + +EmptyRecord ::= SEQUENCE { + +} + +SomeOptionalRecord ::= SEQUENCE { + f0 INTEGER DEFAULT 5, + f1 INTEGER, + f2 INTEGER OPTIONAL, + f3 INTEGER, + f4 INTEGER OPTIONAL, + f5 INTEGER OPTIONAL, + f6 INTEGER, + f7 INTEGER OPTIONAL, + f8 INTEGER, + f9 INTEGER DEFAULT 2 +} + +MyPDV ::= EMBEDDED PDV + +Union ::= CHOICE { + f1 [APPLICATION 64] INTEGER, + f2 [APPLICATION 63] INTEGER, + f3 [APPLICATION 62] INTEGER, + f4 [APPLICATION 16383] INTEGER, + f5 INTEGER, + f6 [PRIVATE 325] INTEGER, + f7 [PRIVATE 7596] INTEGER, + f8 [PRIVATE 18] INTEGER, + f9 [PRIVATE 3] Unsigned1byteInt +} + +MySet ::= SET { + r1 [PRIVATE 2] [PRIVATE 7] REAL, + f1 [PRIVATE 4] INTEGER, + f2 INTEGER OPTIONAL, + f3 [APPLICATION 234] INTEGER, + f4 [APPLICATION 2] INTEGER, + f5 [3] INTEGER, + f6 [1] INTEGER +} + +MyRecordOf ::= SEQUENCE OF SomeOptionalRecord + +MySetOf ::= SET OF MySet + +ROI ::= SEQUENCE OF Unsigned1byteInt + +MyExternal ::= EXTERNAL + + +SUBPRODUCT ::= CLASS { +&code INTEGER (1..99999) UNIQUE, +&OtherFeature +} WITH SYNTAX { CODE &code, OTHERFEATURE &OtherFeature} + + +SubProductCatalog SUBPRODUCT ::= { +{CODE 109, OTHERFEATURE Weight} +} + +SubItem ::= SEQUENCE { + itemCode SUBPRODUCT.&code ({SubProductCatalog }), + otherFeature SUBPRODUCT.&OtherFeature ({SubProductCatalog}{@itemCode}) +} + +PRODUCT ::= CLASS { +&OtherFeature, +&code INTEGER (1..99999) UNIQUE, +&description VisibleString (SIZE (1..100)), +--OpenType-- &Feature +} WITH SYNTAX { OTHERFEATURE &OtherFeature, CODE &code , DESCRIPTION &description , FEATURE &Feature } + +ProductCatalog PRODUCT ::= { +{OTHERFEATURE SubItem, CODE 104, DESCRIPTION "Bookshelf", FEATURE Weight} +} + +Generation ::= ENUMERATED {two-G, three-G, four-G} +Weight ::= IA5String + +Item ::= SEQUENCE { +otherFeature PRODUCT.&OtherFeature ({ProductCatalog}{@itemCode}), +itemCode PRODUCT.&code ({ProductCatalog }), +itemDescription PRODUCT.&description({ProductCatalog}{@itemCode}), +feature PRODUCT.&Feature ({ProductCatalog}{@itemCode}), +isTaxable BOOLEAN +} + + +PersonnelRecord ::= [APPLICATION 0] IMPLICIT SET { + name Name, + title [0] VisibleString, + number EmployeeNumber, + dateOfHire [1] Date, + nameOfSpouse [2] Name, + children [3] IMPLICIT + SEQUENCE OF ChildInformation DEFAULT {} + +} + +ChildInformation ::= SET +{ + name Name, + dateOfBirth [0] Date +} + +Name ::= [APPLICATION 1] IMPLICIT SEQUENCE +{ + givenName VisibleString, + initial VisibleString, + familyName VisibleString +} + +EmployeeNumber ::= [APPLICATION 2] IMPLICIT INTEGER + +Date ::= [APPLICATION 3] IMPLICIT VisibleString -- YYYYMMDD + +johny PersonnelRecord ::= { name {givenName "John", initial "P", familyName "Smith"}, +title "Director", +number 51, +dateOfHire "19710917", +nameOfSpouse {givenName "Mary", initial "T", familyName "Smith"}, +children +{{name {givenName "Ralph", initial "T", familyName "Smith"}, +dateOfBirth "19571111"}, +{name {givenName "Susan", initial "B", familyName "Jones"}, +dateOfBirth "19590717"}}} + + END \ No newline at end of file