Commit 6a82db01 authored by BenceJanosSzabo's avatar BenceJanosSzabo
Browse files

Added seq,set,union extension coding in OER (Bug 527653)



Change-Id: I91636927293f28ef552e314c0cd8f8ba8007cdc6
Signed-off-by: default avatarBenceJanosSzabo <bence.janos.szabo@ericsson.com>
parent 08327474
......@@ -3098,10 +3098,92 @@ void Type::chk_oer() {
}
}
break; }
case T_CHOICE_A:
oerattrib->extendable = t->u.secho.ctss->has_ellipsis();
if (oerattrib->extendable) {
oerattrib->nr_of_root_comps = t->u.secho.ctss->get_nof_root_comps();
}
break;
case T_SET_A: {
oerattrib->extendable = t->u.secho.ctss->has_ellipsis();
if (oerattrib->extendable) {
oerattrib->nr_of_root_comps = t->u.secho.ctss->get_nof_root_comps();
}
// TITAN will reorder the fields for DER coding, which is mostly fine.
// Until the extensions... In OER the DER ordering is good, but the extended
// fields do not need the reordering.
// Here a "map" called p is created which contains the good indexes of the fields.
size_t nElements = t->get_nof_comps();
vector<CompField> se_comps;
map<Tag, CompField> se_comps_map;
for(size_t i=0; i<nElements; i++) {
CompField* cf=t->get_comp_byIndex(i);
Tag *tag = cf->get_type()->get_smallest_tag();
se_comps_map.add(*tag, cf);
delete tag;
}
for(size_t i=0; i<nElements; i++)
se_comps.add(se_comps_map.get_nth_elem(i));
se_comps_map.clear();
size_t limit = oerattrib->extendable ? oerattrib->nr_of_root_comps : nElements;
vector<CompField> se_comps2;
for(size_t i=0; i<limit; i++) {
CompField* cf=t->get_comp_byIndex(i);
Tag *tag = cf->get_type()->get_smallest_tag();
se_comps_map.add(*tag, cf);
delete tag;
}
for(size_t i=0; i<limit; i++)
se_comps2.add(se_comps_map.get_nth_elem(i));
se_comps_map.clear();
for(size_t i=limit; i<nElements; i++)
se_comps2.add(t->get_comp_byIndex(i));
for (size_t i = 0; i < nElements; i++) {
const Identifier& id = se_comps[i]->get_name();
for (size_t j = 0; j < nElements; j++) {
if (id == se_comps2[j]->get_name()) {
oerattrib->p.add(new int(j));
break;
}
}
}
se_comps.clear();
se_comps2.clear();
}
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();
oerattrib->extendable = t->u.secho.ctss->has_ellipsis();
if (oerattrib->extendable) {
oerattrib->nr_of_root_comps = t->u.secho.ctss->get_nof_root_comps();
ExtAdds* eas = t->u.secho.ctss->get_ext_and_exc()->get_eas();
int last_idx = 0;
for (size_t i = 0; i < eas->get_nof_comps(); i++) {
int idx = eas->get_group_byIndex(i);
if (last_idx != 0 && last_idx == idx) {
// do nothing, the field is part of the group
} else if (last_idx != 0 && idx == 0) {
// the group is ended
oerattrib->ext_attr_groups.add(new int(i));
last_idx = 0;
} else if (last_idx != 0 && idx != 0) {
// The group is ended, but new one comes immediately
last_idx = idx;
oerattrib->ext_attr_groups.add(new int(i));
oerattrib->ext_attr_groups.add(new int(i));
} else if (last_idx == 0 && idx != 0) {
// new group
last_idx = idx;
oerattrib->ext_attr_groups.add(new int(i));
}
}
if (last_idx != 0) {
oerattrib->ext_attr_groups.add(new int(eas->get_nof_comps()));
}
}
if (t->typetype != T_SET_A) {
for (size_t i = 0; i < t->get_nof_comps(); i++)
oerattrib->p.add(new int(i));
}
break; }
case T_SEQOF:
......
......@@ -1087,16 +1087,47 @@ 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, -1, FALSE };\n"
"const TTCN_OERdescriptor_t %s_oer_ = { -1, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL };\n"
, get_genname_own().c_str());
} else {
target->source.global_vars = mputprintf(target->source.global_vars,
"const int %s_oer_ext_arr_[%lu] = {"
, get_genname_own().c_str()
, oerattrib->ext_attr_groups.size());
for (size_t i = 0; i < oerattrib->ext_attr_groups.size(); i++) {
target->source.global_vars = mputprintf(target->source.global_vars,
"%i", *oerattrib->ext_attr_groups[i]);
if (i != oerattrib->ext_attr_groups.size() - 1) {
target->source.global_vars = mputstr(target->source.global_vars, ", ");
}
}
target->source.global_vars = mputstr(target->source.global_vars, "};\n");
target->source.global_vars = mputprintf(target->source.global_vars,
"const int %s_oer_p_[%lu] = {"
, get_genname_own().c_str()
, oerattrib->p.size());
for (size_t i = 0; i < oerattrib->p.size(); i++) {
target->source.global_vars = mputprintf(target->source.global_vars,
"%i", *oerattrib->p[i]);
if (i != oerattrib->p.size() - 1) {
target->source.global_vars = mputstr(target->source.global_vars, ", ");
}
}
target->source.global_vars = mputstr(target->source.global_vars, "};\n");
target->source.global_vars = mputprintf(target->source.global_vars,
"const TTCN_OERdescriptor_t %s_oer_ = { %i, %s, %i, %s };\n"
"const TTCN_OERdescriptor_t %s_oer_ = { %i, %s, %i, %s, %i, %lu, %s_oer_ext_arr_, %lu, %s_oer_p_"
, get_genname_own().c_str()
, oerattrib->bytes
, oerattrib->signed_ ? "TRUE" : "FALSE"
, oerattrib->length
, oerattrib->extendable ? "TRUE" : "FALSE");
, oerattrib->extendable ? "TRUE" : "FALSE"
, oerattrib->nr_of_root_comps
, oerattrib->ext_attr_groups.size()
, get_genname_own().c_str()
, oerattrib->p.size()
, get_genname_own().c_str());
target->source.global_vars = mputstr(target->source.global_vars, "};\n");
}
}
......@@ -1219,6 +1250,10 @@ void Type::generate_code_Choice(output_struct *target)
get_gen_coder_functions(CT_XER);
sdef.hasJson = get_gen_coder_functions(CT_JSON);
sdef.hasOer = get_gen_coder_functions(CT_OER);
if (oerattrib) {
sdef.oerExtendable = oerattrib->extendable;
sdef.oerNrOrRootcomps = oerattrib->nr_of_root_comps;
}
sdef.has_opentypes = get_has_opentypes();
sdef.opentype_outermost = get_is_opentype_outermost();
sdef.ot = generate_code_ot(pool);
......@@ -1632,6 +1667,20 @@ void Type::generate_code_Se(output_struct *target)
get_gen_coder_functions(CT_XER);
sdef.hasJson = get_gen_coder_functions(CT_JSON);
sdef.hasOer = get_gen_coder_functions(CT_OER);
if (oerattrib) {
sdef.oerExtendable = oerattrib->extendable;
sdef.oerNrOrRootcomps = oerattrib->nr_of_root_comps;
sdef.oerEagNum = oerattrib->ext_attr_groups.size();
sdef.oerEag = (int*)Malloc(sdef.oerEagNum*sizeof(int));
for (int i = 0; i < sdef.oerEagNum; i++) {
sdef.oerEag[i] = *(oerattrib->ext_attr_groups[i]);
}
sdef.oerPNum = oerattrib->p.size();
sdef.oerP = (int*)Malloc(sdef.oerPNum*sizeof(int));
for (int i = 0; i < sdef.oerPNum; i++) {
sdef.oerP[i] = *(oerattrib->p[i]);
}
}
if (xerattrib){
Module *my_module = get_my_scope()->get_scope_mod();
sdef.xerHasNamespaces = my_module->get_nof_ns() != 0;
......@@ -2046,6 +2095,12 @@ void Type::generate_code_Se(output_struct *target)
}
}
Free(sdef.elements);
if (sdef.oerEag) {
Free(sdef.oerEag);
}
if (sdef.oerP) {
Free(sdef.oerP);
}
}
bool Type::is_untagged() const { return xerattrib && xerattrib->untagged_; }
......
......@@ -709,6 +709,19 @@ namespace Common {
get_fullname().c_str(), (unsigned long) n);
return 0;
}
int ExtAdds::get_group_byIndex(size_t n) const
{
size_t offset = n;
for(size_t i = 0; i < eas.size(); i++) {
size_t size = eas[i]->get_nof_comps();
if (offset < size) return eas[i]->get_group_number();
else offset -= size;
}
FATAL_ERROR("%s: Requested index %lu does not exist.", \
get_fullname().c_str(), (unsigned long) n);
return 0;
}
bool ExtAdds::has_comp_withName(const Identifier& p_name) const
{
......@@ -737,6 +750,10 @@ namespace Common {
{
if(!p_ea)
FATAL_ERROR("NULL parameter: Asn::ExtAdds::add_ea()");
if (p_ea->is_ext_attr_group()) {
num_of_groups++;
p_ea->set_group_number(num_of_groups);
}
eas.add(p_ea);
}
......
......@@ -130,6 +130,7 @@ namespace Common {
bool has_comp_withName(const Identifier& p_name);
CompField* get_comp_byName(const Identifier& p_name);
void tr_compsof(ReferenceChain *refch, bool in_ellipsis);
ExtAndExc* get_ext_and_exc() const { return ee; }
bool has_ellipsis() const { return ee != 0; }
bool needs_auto_tags();
void add_auto_tags();
......@@ -160,6 +161,9 @@ namespace Common {
virtual bool has_comp_withName(const Identifier& p_name) const = 0;
virtual CompField* get_comp_byName(const Identifier& p_name) const = 0;
virtual void tr_compsof(ReferenceChain *refch, bool is_set) = 0;
virtual bool is_ext_attr_group() const { return false; }
virtual int get_group_number() const { return 0; }
virtual void set_group_number(int) {}
};
/**
......@@ -168,18 +172,21 @@ namespace Common {
class ExtAdds : public Node {
private:
vector<ExtAdd> eas;
// The number of ExtAddGrps
int num_of_groups;
/** Copy constructor not implemented */
ExtAdds(const ExtAdds& p);
/** Assignment disabled */
ExtAdds& operator=(const ExtAdds& p);
public:
ExtAdds() : Node(), eas() { }
ExtAdds() : Node(), eas(), num_of_groups(0) { }
virtual ~ExtAdds();
virtual ExtAdds *clone() const;
virtual void set_fullname(const string& p_fullname);
virtual void set_my_scope(Scope *p_scope);
size_t get_nof_comps() const;
CompField* get_comp_byIndex(size_t n) const;
int get_group_byIndex(size_t n) const;
bool has_comp_withName(const Identifier& p_name) const;
CompField* get_comp_byName(const Identifier& p_name) const;
void tr_compsof(ReferenceChain *refch, bool is_set);
......@@ -215,6 +222,7 @@ namespace Common {
void tr_compsof(ReferenceChain *refch, bool is_set)
{ eas->tr_compsof(refch, is_set); }
void set_eas(ExtAdds *p_eas);
ExtAdds * get_eas() const { return eas; }
virtual void dump(unsigned level) const;
};
......@@ -226,6 +234,8 @@ namespace Common {
/** can be NULL if not present */
Value *versionnumber;
CTs *cts;
// Needed for oer coding
int groupnumber;
/** Copy constructor not implemented */
ExtAddGrp(const ExtAddGrp& p);
/** Assignment disabled */
......@@ -242,6 +252,10 @@ namespace Common {
virtual CompField* get_comp_byName(const Identifier& p_name) const;
virtual void tr_compsof(ReferenceChain *refch, bool is_set);
virtual void dump(unsigned level) const;
virtual bool is_ext_attr_group() const { return true; }
virtual int get_group_number() const { return groupnumber; }
virtual void set_group_number(int num) { groupnumber = num; }
};
/**
......
......@@ -104,6 +104,12 @@ typedef struct {
boolean hasXer;
boolean hasJson;
boolean hasOer;
boolean oerExtendable;
int oerNrOrRootcomps;
int oerEagNum;
int* oerEag;
int oerPNum;
int* oerP;
boolean xerUntagged;
boolean xerUntaggedOne; /**< from Type::u.secho.has_single_charenc */
boolean xerUseNilPossible; /* for sequence */
......
......@@ -4655,56 +4655,193 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
if (oer_needed) {
// OER encode, RT1
src = mputprintf(src,
"int %s::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const\n"
"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 %s value.\");\n"
" return -1;\n"
" }\n", name, sdef->kind == SET ? "set" : "record");
if (sdef->oerExtendable && sdef->oerNrOrRootcomps != sdef->nElements) {
src = mputstr(src,
" boolean has_extension = FALSE;\n");
for (i = sdef->oerNrOrRootcomps; i < sdef->nElements; i++) {
src = mputprintf(src,
" has_extension = has_extension || (field_%s.is_bound() && field_%s.is_present());\n",
sdef->elements[i].name, sdef->elements[sdef->oerP[i]].name);
}
}
size_t opt_elements = 0;
for (i = 0; i < sdef->nElements; i++) {
if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) {
size_t limit = sdef->oerExtendable ? sdef->oerNrOrRootcomps : sdef->nElements;
for (i = 0; i < limit; i++) {
if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[i]].isDefault) {
opt_elements++;
}
}
int needed_bytes = opt_elements / 8 + 1;
int bits = opt_elements+(sdef->oerExtendable == TRUE);
int needed_bytes = bits / 8 + (bits % 8 == 0 ? 0 : 1);
if (opt_elements != 0) {
src = mputprintf(src,
" unsigned char c[%i] = {0};\n"
, needed_bytes);
int pos = 8;
if (opt_elements != 0 || sdef->oerExtendable) {
src = mputstr(src,
" char c = 0;\n");
if (sdef->oerExtendable && sdef->oerNrOrRootcomps != sdef->nElements) {
pos--;
src = mputprintf(src,
" if (has_extension) {\n"
" c += %i;\n"
" }\n", 1 << 7);
}
}
int ind = 0;
int pos = 8;
for (i = 0; i < sdef->nElements; i++) {
if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) {
for (i = 0; i < limit; i++) {
if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[i]].isDefault) {
pos--;
src = mputprintf(src,
" if (field_%s.is_present()) {\n"
" c[%i] += 1 << %i;\n"
" c += %i;\n"
" }\n"
, sdef->elements[i].name, ind, pos);
, sdef->elements[sdef->oerP[i]].name
, 1 << pos);
if (pos == 0) {
pos = 8;
ind++;
src = mputstr(src,
" p_buf.put_c(c);\n"
" c = 0\n;");
}
}
}
if (opt_elements != 0) {
src = mputprintf(src,
" p_buf.put_s(%i, c);\n"
, needed_bytes);
if (opt_elements != 0 || sdef->oerExtendable) {
if (pos != 8 || ind == 0) {
src = mputstr(src,
" p_buf.put_c(c);\n");
}
}
for (i = 0; i < sdef->nElements; i++) {
if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) {
for (i = 0; i < limit; i++) {
if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[i]].isDefault) {
src = mputprintf(src,
" if (field_%s.is_present())\n "
, sdef->elements[i].name);
, sdef->elements[sdef->oerP[i]].name);
}
src = mputprintf(src,
" field_%s.OER_encode(%s_descr_, p_buf);\n"
, sdef->elements[i].name, sdef->elements[i].typedescrname);
, sdef->elements[sdef->oerP[i]].name, sdef->elements[sdef->oerP[i]].typedescrname);
}
if (sdef->oerExtendable && sdef->oerNrOrRootcomps != sdef->nElements) {
bits = 0;
int eag_pos = 0;
for (i = limit; i < sdef->nElements; i++) {
if (sdef->oerEagNum != 0 && sdef->oerEag[eag_pos] == i - limit) {
eag_pos++;
bits++;
i += sdef->oerEag[eag_pos] - sdef->oerEag[eag_pos-1] - 1;
eag_pos++;
} else {
bits++;
}
}
needed_bytes = bits / 8 + (bits % 8 == 0 ? 0 : 1);
src = mputprintf(src,
" if (has_extension) {\n"
"%s"
" TTCN_Buffer tmp_buf;\n"
" TTCN_Buffer tmp_buf2;\n"
" TTCN_Buffer tmp_buf3;\n"
" c = 0;\n"
, sdef->oerEagNum != 0 ? " boolean has_present = FALSE;\n" : "");
eag_pos = 0;
pos = 8;
ind = 0;
for (i = limit; i < sdef->nElements; i++) {
pos--;
if (sdef->oerEagNum != 0 && sdef->oerEag[eag_pos] == i - limit) {
eag_pos++;
int opt_elems = 0;
for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) {
if (sdef->elements[sdef->oerP[j]].isOptional || sdef->elements[sdef->oerP[j]].isDefault) {
opt_elems++;
}
src = mputprintf(src,
" has_present = has_present || field_%s.is_present();\n", sdef->elements[sdef->oerP[j]].name);
}
src = mputprintf(src,
" if (has_present) {\n"
" has_present = FALSE;\n"
" c += %i;\n", 1 << pos);
if (opt_elems != 0) {
src = mputstr(src,
" char c2 = 0;\n");
int pos2 = 8;
int ind2 = 0;
for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) {
if (sdef->elements[sdef->oerP[j]].isOptional || sdef->elements[sdef->oerP[j]].isDefault) {
pos2--;
src = mputprintf(src,
" if (field_%s.is_present()) {\n"
" c2 += %i;\n"
" }\n"
, sdef->elements[sdef->oerP[j]].name, 1 << pos2);
if (pos2 == 0) {
pos2 = 8;
ind2++;
src = mputstr(src,
" tmp_buf2.put_c(c2);\n"
" c2 = 0;\n");
}
}
}
if (pos2 != 8) {
src = mputstr(src,
" tmp_buf2.put_c(c2);\n");
}
}
for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) {
src = mputprintf(src,
" field_%s.OER_encode(%s_descr_, tmp_buf2);\n"
, sdef->elements[sdef->oerP[j]].name, sdef->elements[sdef->oerP[j]].typedescrname);
}
src = mputstr(src,
" encode_oer_length(tmp_buf2.get_len(), tmp_buf, FALSE);\n"
" tmp_buf.put_buf(tmp_buf2);\n"
" tmp_buf2.clear();\n"
" }\n");
i += sdef->oerEag[eag_pos] - sdef->oerEag[eag_pos-1] - 1;
eag_pos++;
} else {
src = mputprintf(src,
" if (field_%s.is_present()) {\n"
" c += %i;\n"
" field_%s.OER_encode(%s_descr_, tmp_buf2);\n"
" encode_oer_length(tmp_buf2.get_len(), tmp_buf, FALSE);\n"
" tmp_buf.put_buf(tmp_buf2);\n"
" tmp_buf2.clear();\n"
" }\n"
, sdef->elements[sdef->oerP[i]].name, 1 << pos
, sdef->elements[sdef->oerP[i]].name, sdef->elements[sdef->oerP[i]].typedescrname);
}
if (pos == 0) {
ind++;
pos = 8;
src = mputstr(src,
" tmp_buf3.put_c(c);\n"
" c = 0;\n");
}
}
if (pos != 8) {
src = mputstr(src,
" tmp_buf3.put_c(c);\n");
}
src = mputprintf(src,
" encode_oer_length(%i, p_buf, FALSE);\n"
" p_buf.put_c(%i);\n"
" p_buf.put_buf(tmp_buf3);\n"
" p_buf.put_buf(tmp_buf);\n"
" tmp_buf.clear();\n"
" }\n", needed_bytes+1, pos);
}
src = mputstr(src,
" return 0;\n"
......@@ -4714,7 +4851,9 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
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) {
bits = opt_elements+(sdef->oerExtendable == TRUE);
needed_bytes = bits / 8 + (bits % 8 == 0 ? 0 : 1);
if (needed_bytes != 0) {
src = mputprintf(src,
" const unsigned char* uc = p_buf.get_read_data();\n"
" p_buf.increase_pos(%i);\n"
......@@ -4722,18 +4861,26 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
}
ind = 0;
pos = 8;
for (i = 0; i < sdef->nElements; i++) {
if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) {
if (sdef->oerExtendable) {
src = mputstr(src,
" boolean has_extension = FALSE;\n"
" if (uc[0] & 0x80) {\n"
" has_extension = TRUE;\n"
" }\n");
pos--;
}
for (i = 0; i < limit; i++) {
if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[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) {
, sdef->elements[sdef->oerP[i]].typedescrname);
if (sdef->elements[sdef->oerP[i]].isOptional) {
src = mputprintf(src, " else\n"
" field_%s = OMIT_VALUE;\n"
, sdef->elements[i].name);
, sdef->elements[sdef->oerP[i]].name);
}
if (pos == 0) {
ind++;
......@@ -4742,10 +4889,104 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
} else {
src = mputprintf(src,
" field_%s.OER_decode(%s_descr_, p_buf, p_oer);\n"
, sdef->elements[i].name
, sdef->elements[i].typedescrname);
, sdef->elements[sdef->oerP[i]].name
, sdef->elements[sdef->oerP[i]].typedescrname);
}
}
if (sdef->oerExtendable) {
src = mputstr(src,
" if (has_extension) {\n"
" size_t bytes = decode_oer_length(p_buf, FALSE);\n"
" uc = p_buf.get_read_data();\n"
" p_buf.increase_pos(bytes);\n"
" uc++;\n");
int eag_pos = 0;
pos = 8;
ind = 0;
for (i = limit; i < sdef->nElements; i++) {
pos--;
src = mputprintf(src,
" if (!(uc[%i] & %i)) {\n"
, ind, 1 << pos);
if (sdef->oerEagNum != 0 && sdef->oerEag[eag_pos] == i - limit) {
eag_pos++;
for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) {
if (sdef->elements[sdef->oerP[j]].isOptional) {
src = mputprintf(src,