Commit 782712ad authored by BenceJanosSzabo's avatar BenceJanosSzabo
Browse files

XER: Untagged optional record decoding works correctly when omitted (Bug 506202)



Change-Id: Ifc955ba60e28bc71481e5808c9180bab09984d20
Signed-off-by: default avatarBenceJanosSzabo <bence.janos.szabo@ericsson.com>
parent 366def82
......@@ -3041,6 +3041,13 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc)
" }\n"
, sdef->elements[i].name);
}
if (!sdef->elements[i].isOptional) {
src = mputprintf(src,
" if (field_%s.is_bound()) {\n"
" p_flavor &= ~XER_OPTIONAL;\n"
" }\n"
, sdef->elements[i].name);
}
} /* next field */
if (i == start_at + num_attributes) {
......@@ -3117,6 +3124,10 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc)
if (!sdef->elements[i].isOptional) {
src = mputprintf(src,
" if (!field_%s.is_bound()) {\n"
" if (p_flavor & XER_OPTIONAL) {\n"
" clean_up();\n"
" return -1;\n"
" }\n"
" TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,\n"
" \"No data found for non-optional field '%s'\");\n"
" }\n"
......
......@@ -1428,6 +1428,9 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
/* The call to the non-const operator[] creates a new element object,
* then we call its XER_decode with the temporary XML reader. */
" (*this)[val_ptr->n_elements].XER_decode(*p_td.oftype_descr, reader_2, p_flavor, p_flavor2, 0);\n"
" if ((*this)[val_ptr->n_elements - 1].is_bound()) {\n"
" p_flavor &= ~XER_OPTIONAL;\n"
" }\n"
" if (p_flavor & EXIT_ON_ERROR && !(*this)[val_ptr->n_elements - 1].is_bound()) {\n"
" if (1 == val_ptr->n_elements) {\n"
// Failed to decode even the first element
......
......@@ -3394,6 +3394,11 @@ int CHARACTER_STRING::XER_decode(const XERdescriptor_t& p_td,
for (; success == 1; success = reader.Read()) {
type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
depth = reader.Depth();
reader.Read();
......
......@@ -3413,6 +3413,11 @@ int EMBEDDED_PDV::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
for (success = reader.Ok(); success == 1; success = reader.Read()) {
type = reader.NodeType();
if (type==XML_READER_TYPE_ELEMENT) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
depth = reader.Depth();
reader.Read();
......
......@@ -603,6 +603,11 @@ namespace { /* anonymous namespace */
for (; success == 1; success = reader.Read()) {
int type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
depth = reader.Depth();
reader.Read();
......
......@@ -266,6 +266,11 @@ int ASN_NULL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
for (; success == 1; success = reader.Read()) {
int type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
depth = reader.Depth();
break;
......
......@@ -1104,6 +1104,11 @@ int BITSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
for (; success == 1; success = reader.Read()) {
type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
depth = reader.Depth();
if (reader.IsEmptyElement()) {
......
......@@ -663,6 +663,11 @@ int BOOLEAN::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
type = reader.NodeType();
if (!notag && depth == -1) {
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
depth = reader.Depth();
......
......@@ -1372,6 +1372,11 @@ int CHARSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
for (; success == 1; success = reader.Read()) {
int type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
if (reader.IsEmptyElement()) { // has no text, needs special processing
if (exer && p_td.dfeValue != 0) {
......
......@@ -989,6 +989,11 @@ tagless:
for (; success == 1; success = reader.Read()) {
int type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
if (reader.IsEmptyElement()) {
if (exer && p_td.dfeValue != 0) {
......
......@@ -937,6 +937,11 @@ int HEXSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
if (own_tag) for (; success == 1; success = reader.Read()) {
type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
depth = reader.Depth();
if (reader.IsEmptyElement()) {
......
......@@ -1647,6 +1647,11 @@ tagless:
for (; success == 1; success = reader.Read()) {
type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
if (reader.IsEmptyElement()) {
if (exer && p_td.dfeValue != 0) {
......
......@@ -566,6 +566,11 @@ int OBJID::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
for (; success == 1; success = reader.Read()) {
int type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
depth = reader.Depth();
break;
......
......@@ -975,6 +975,11 @@ int OCTETSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
if (own_tag) for (; success == 1; success = reader.Read()) {
type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
depth = reader.Depth();
if (reader.IsEmptyElement()) {
......
......@@ -1102,7 +1102,8 @@ OPTIONAL<T_type>::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
found_it:
set_to_present();
//success = reader.Read(); // move to next thing TODO should it loop till an element ?
optional_value->XER_decode(p_td, reader, flavor, flavor2, emb_val);
// Pass XER_OPTIONAL to flavor, to sign that we are optional
optional_value->XER_decode(p_td, reader, flavor | XER_OPTIONAL, flavor2, emb_val);
if (!optional_value->is_bound()) {
set_to_omit();
}
......
......@@ -2148,6 +2148,11 @@ int UNIVERSAL_CHARSTRING::XER_decode(const XERdescriptor_t& p_td,
if (!omit_tag) for (; success == 1; success = reader.Read()) {
int type = reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((flavor & XER_OPTIONAL) && !check_name((const char*)reader.LocalName(), p_td, exer)) {
return -1;
}
verify_name(reader, p_td, exer);
if (reader.IsEmptyElement()) {
if (exer && p_td.dfeValue != 0) {
......
......@@ -332,6 +332,12 @@ int VERDICTTYPE::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader
if (name_tag) for (; rd_ok == 1; rd_ok = p_reader.Read()) {
type = p_reader.NodeType();
if (XML_READER_TYPE_ELEMENT == type) {
// If our parent is optional and there is an unexpected tag then return and
// we stay unbound.
if ((p_flavor & XER_OPTIONAL) && !check_name((const char*)p_reader.LocalName(), p_td, e_xer)) {
return -1;
}
verify_name(p_reader, p_td, e_xer);
rd_ok = p_reader.Read();
break;
}
......
......@@ -57,7 +57,6 @@ enum XER_flavor {
XER_EXTENDED = 1U << 2, /**< Extended XER */
DEF_NS_PRESENT = 1U << 3, // 0x08
DEF_NS_SQUASHED = 1U << 4, // 0x10
XER_MASK = 0x1FU, /**< All the "real" XER flavors plus DEF_NS */
/* Additional flags, for the parent to pass information to its children
* (when the parent affects the child, e.g. LIST) */
......@@ -100,7 +99,10 @@ enum XER_flavor {
EXIT_ON_ERROR = 1U << 29, /* 0x20000000 clean up and exit instead of throwing
a decoding error, used on alternatives of a union with USE-UNION */
XER_OPTIONAL = 1U << 30, // 0x40000000 is an optional field of a record or set
BLOCKED = 1U << 31 // 0x80000000 either ABSTRACT or BLOCK
BLOCKED = 1U << 31, // 0x80000000 either ABSTRACT or BLOCK
/**< All the "real" XER flavors plus DEF_NS + XER_OPTIONAL*/
XER_MASK = 0x1FU | XER_OPTIONAL
};
enum XER_flavor2 {
......
......@@ -2399,6 +2399,9 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
ec_1.set_msg("%d: ", get_nof_elements());
/* The call to the non-const get_at() creates the element */
get_at(get_nof_elements())->XER_decode(*p_td.oftype_descr, reader, flavor, flavor2, emb_val);
if (get_at(get_nof_elements()-1)->is_bound()) {
flavor &= ~XER_OPTIONAL;
}
}
if (0 != emb_val && !own_tag && get_nof_elements() > 1 && !(p_td.oftype_descr->xer_bits & UNTAGGED)) {
++emb_val->embval_index;
......@@ -5589,7 +5592,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
}
} // not empty element
}
else { // not USE-ORDER, simpler code
else { // not USE-ORDER, simpler code
if (usenil_attribute) {
reader.MoveToElement(); // value absent, nothing more to do
} else {
......@@ -5642,6 +5645,10 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
if (tag_closed) new_flavor |= PARENT_CLOSED;
get_at(i)->XER_decode(*xer_descr(i), reader, new_flavor, flavor2, emb_val);
if (!get_at(i)->is_optional() && get_at(i)->is_bound()) {
// Remove XER_OPTIONAL when we found a non optional field which is bound
flavor &= ~XER_OPTIONAL;
}
}
}
if (!get_at(i)->is_present()) {
......@@ -5683,6 +5690,12 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
// Check if every non-optional field has been set
for (i = 0; i < field_cnt; ++i) {
if (!get_at(i)->is_optional() && !get_at(i)->is_bound()) {
if (flavor & XER_OPTIONAL) {
// If there is a non optional field which is unbound and we are optional
// then set to omit. Test: RecordOmit
clean_up();
return -1;
}
TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
"No data found for non-optional field '%s'", fld_name(i));
}
......
......@@ -29,7 +29,8 @@ endif
XDIRS := $(wildcard $(SHADOWED)) xsdConverter \
HM60295 HN15589 HQ30408 HR49727 HU13380 $(RT2_ONLY) \
XmlWorkflow tpdValidTest AbstractBlock UseNilLong AttributeFormDefault
XmlWorkflow tpdValidTest AbstractBlock UseNilLong AttributeFormDefault \
RecordOmit
# List of fake targets:
.PHONY: all dep clean run $(XDIRS) $(addsuffix /, $(XDIRS)) profile
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment