Commit 012d72e5 authored by BenceJanosSzabo's avatar BenceJanosSzabo
Browse files

Implemented OER coding: part2 (Bug 522222)



Change-Id: I20cabdf94fd2fa78df8bc7b95475b8d750520f84
Signed-off-by: default avatarBenceJanosSzabo <bence.janos.szabo@ericsson.com>
parent 820f4259
......@@ -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;
......
......@@ -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;
}
......
......@@ -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");
}
}
......
......@@ -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"
......
......@@ -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");
......
......@@ -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");
......
......@@ -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"