-///////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2000-2014 Ericsson Telecom AB
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// which accompanies this distribution, and is available at
-// http://www.eclipse.org/legal/epl-v10.html
-///////////////////////////////////////////////////////////////////////////////
+/******************************************************************************
+ * Copyright (c) 2000-2016 Ericsson Telecom AB
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Baji, Laszlo
+ * Balasko, Jeno
+ * Baranyi, Botond
+ * Beres, Szabolcs
+ * Cserveni, Akos
+ * Delic, Adam
+ * Feher, Csaba
+ * Forstner, Matyas
+ * Kovacs, Ferenc
+ * Kremer, Peter
+ * Ormandi, Matyas
+ * Pandi, Krisztian
+ * Raduly, Csaba
+ * Szabados, Kristof
+ * Szabo, Bence Janos
+ * Szabo, Janos Zoltan – initial implementation
+ * Szalai, Gabor
+ * Pandi, Krisztian
+ *
+ ******************************************************************************/
#include <string.h>
#include "../common/memory.h"
"{\n"
"switch (other_value.union_selection) {\n", name, name);
for (i = 0; i < sdef->nElements; i++) {
- src = mputprintf(src, "case %s_%s:\n"
- "field_%s = new %s(*other_value.field_%s);\n"
- "break;\n", selection_prefix, sdef->elements[i].name,
+ src = mputprintf(src, "case %s_%s:\n", selection_prefix, sdef->elements[i].name);
+ if (legacy_unbound_union_fields) {
+ src = mputprintf(src, "if (other_value.field_%s->is_bound()) ",
+ sdef->elements[i].name);
+ }
+ src = mputprintf(src, "field_%s = new %s(*other_value.field_%s);\n",
sdef->elements[i].name, sdef->elements[i].type, sdef->elements[i].name);
+ if (legacy_unbound_union_fields) {
+ src = mputprintf(src,
+ "else {\n"
+ "field_%s = new %s;\n"
+ "TTCN_warning(\"Assignment of a union value with an unbound selected "
+ "alternative\");\n"
+ "}\n", sdef->elements[i].name, sdef->elements[i].type);
+ }
+ src = mputstr(src, "break;\n");
}
src = mputprintf(src, "default:\n"
"TTCN_error(\"Assignment of an unbound union value of type %s.\");\n"
"param.error(\"Field `%%s' not found in union type `%s'\", param_field);\n"
" }\n"
" param.basic_check(Module_Param::BC_VALUE, \"union value\");\n"
- " if (param.get_type()==Module_Param::MP_Value_List && param.get_size()==0) return;\n"
- " if (param.get_type()!=Module_Param::MP_Assignment_List) {\n"
+ " Module_Param_Ptr m_p = ¶m;\n"
+ " if (param.get_type() == Module_Param::MP_Reference) {\n"
+ " m_p = param.get_referenced_param();\n"
+ " }\n"
+ " if (m_p->get_type()==Module_Param::MP_Value_List && m_p->get_size()==0) return;\n"
+ " if (m_p->get_type()!=Module_Param::MP_Assignment_List) {\n"
" param.error(\"union value with field name was expected\");\n"
" }\n"
- " Module_Param* mp_last = param.get_elem(param.get_size()-1);\n", dispname);
+ " Module_Param* mp_last = m_p->get_elem(m_p->get_size()-1);\n", dispname);
- for (i = 0; i < sdef->nElements; i++) {
+ for (i = 0; i < sdef->nElements; i++) {
src = mputprintf(src,
" if (!strcmp(mp_last->get_id()->get_name(), \"%s\")) {\n"
" %s%s().set_param(*mp_last);\n"
- " return;\n"
- " }\n", sdef->elements[i].dispname, at_field, sdef->elements[i].name);
+ " if (!%s%s().is_bound()) "
+ , sdef->elements[i].dispname, at_field, sdef->elements[i].name
+ , at_field, sdef->elements[i].name);
+ if (legacy_unbound_union_fields) {
+ src = mputprintf(src,
+ "TTCN_warning(\"Alternative '%s' was selected for union of type '%s', "
+ "but its value is unbound\");\n"
+ , sdef->elements[i].dispname, sdef->dispname);
}
+ else {
+ // a union's alternative cannot be unbound
+ src = mputstr(src, "clean_up();\n");
+ }
+ src = mputstr(src,
+ " return;\n"
+ " }\n");
+ }
src = mputprintf(src,
" mp_last->error(\"Field %%s does not exist in type %s.\", mp_last->get_id()->get_name());\n"
"}\n\n", dispname);
+
+ /* get param function */
+ def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
+ src = mputprintf(src,
+ "Module_Param* %s::get_param(Module_Param_Name& param_name) const\n"
+ "{\n"
+ " if (!is_bound()) {\n"
+ " return new Module_Param_Unbound();\n"
+ " }\n"
+ " if (param_name.next_name()) {\n"
+ // Haven't reached the end of the module parameter name
+ // => the name refers to one of the fields, not to the whole union
+ " char* param_field = param_name.get_current_name();\n"
+ " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
+ " TTCN_error(\"Unexpected array index in module parameter reference, \"\n"
+ " \"expected a valid field name for union type `%s'\");\n"
+ " }\n"
+ " ", name, dispname);
+ for (i = 0; i < sdef->nElements; i++) {
+ src = mputprintf(src,
+ "if (strcmp(\"%s\", param_field) == 0) {\n"
+ " return %s%s().get_param(param_name);\n"
+ " } else ",
+ sdef->elements[i].dispname, at_field, sdef->elements[i].name);
+ }
+ src = mputprintf(src,
+ "TTCN_error(\"Field `%%s' not found in union type `%s'\", param_field);\n"
+ " }\n"
+ " Module_Param* mp_field = NULL;\n"
+ " switch(union_selection) {\n"
+ , name);
+ for (i = 0; i < sdef->nElements; ++i) {
+ src = mputprintf(src,
+ " case %s_%s:\n"
+ " mp_field = field_%s->get_param(param_name);\n"
+ " mp_field->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n"
+ " break;\n"
+ , selection_prefix, sdef->elements[i].name
+ , sdef->elements[i].name, sdef->elements[i].dispname);
+ }
+ src = mputstr(src,
+ " default:\n"
+ " break;\n"
+ " }\n"
+ " Module_Param_Assignment_List* m_p = new Module_Param_Assignment_List();\n"
+ " m_p->add_elem(mp_field);\n"
+ " return m_p;\n"
+ "}\n\n");
/* set implicit omit function, recursive */
def = mputstr(def, " void set_implicit_omit();\n");
for (i = 0; i < sdef->nElements; i++) {
if ((tag_type[i] > 0)
&& (sdef->raw.taglist.list + tag_type[i] - 1)->nElements) {
- src = mputstr(src, " boolean already_failed = FALSE;\n"
- " raw_order_t local_top_order;\n");
+ src = mputstr(src, " boolean already_failed = FALSE;\n");
break;
}
}
}
if (temp_variable_list[variable_index].decoded_for_element
== -1) {
- src = mputstr(src, " ");
- for (k = cur_field_list->nElements - 1; k > 0; k--) {
- src = mputprintf(src,
- " if(%s_descr_.raw->top_bit_order==TOP_BIT_RIGHT)"
- "local_top_order=ORDER_MSB;\n"
- " else if(%s_descr_.raw->top_bit_order==TOP_BIT_LEFT)"
- "local_top_order=ORDER_LSB;\n"
- " else", cur_field_list->fields[k - 1].typedescr,
- cur_field_list->fields[k - 1].typedescr);
- }
- src = mputprintf(src, " local_top_order=top_bit_ord;\n"
+ src = mputprintf(src,
" p_buf.set_pos_bit(starting_pos + %d);\n"
" decoded_%lu_length = temporal_%lu.RAW_decode("
"%s_descr_, p_buf, limit, top_bit_ord, TRUE);\n",
src = mputprintf(src, /* XERSTUFF XER_encode for union */
"int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
- "unsigned int p_flavor, int p_indent) const\n"
+ "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n"
"{\n"
"%s"
" if (%s==union_selection) {\n"
" int encoded_length=(int)p_buf.get_len();\n"
, name
, (use_runtime_2 ? " if (err_descr) return XER_encode_negtest"
- "(err_descr, p_td, p_buf, p_flavor, p_indent);\n" : "")
+ "(err_descr, p_td, p_buf, p_flavor, p_indent, 0);\n" : "")
, unbound_value
);
src = mputstr(src,
" const boolean e_xer = is_exer(p_flavor);\n"
" char *type_atr = NULL;\n"
- " unsigned short name_len = 0;\n"
" if (e_xer && (p_td.xer_bits & USE_TYPE_ATTR)) {\n"
- " const char *type_name = 0;\n"
+ " char *type_name = 0;\n"
" const namespace_t *control_ns;\n"
" switch (union_selection) {\n");
/* In case of USE-TYPE the first field won't need the type attribute */
for (i = start_at; i < sdef->nElements; i++) {
src = mputprintf(src,
" case %s_%s:\n"
- " type_name = %s_xer_.names[1];\n"
- " name_len = %s_xer_.namelens[1] - 2;\n"
+ " if (%s_xer_.my_module != 0 && %s_xer_.ns_index != -1 &&\n"
+ " %s_xer_.namelens[1] > 2) {\n"
+ /* add the namespace prefix to the type attribute (if the name is not empty) */
+ " const namespace_t *my_ns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
+ " if (my_ns->px[0] != 0) {\n"
+ " type_name = mprintf(\"%%s:\", my_ns->px);\n"
+ " }\n"
+ " }\n"
+ " type_name = mputstrn(type_name, %s_xer_.names[1], %s_xer_.namelens[1] - 2);\n"
" %s\n"
, selection_prefix, sdef->elements[i].name
- , sdef->elements[i].typegen
+ , sdef->elements[i].typegen, sdef->elements[i].typegen
+ , sdef->elements[i].typegen, sdef->elements[i].typegen
+ , sdef->elements[i].typegen, sdef->elements[i].typegen
, sdef->elements[i].typegen
, i < sdef->nElements - 1 ? "goto write_atr;" : "" /* no break */
);
}
src = mputprintf(src,
"%s" /* label only if more than two elements total */
- " if (name_len > 0) {\n" /* 38.3.8, no atr if NAME AS "" */
+ " if (mstrlen(type_name) > 0) {\n" /* 38.3.8, no atr if NAME AS "" */
" control_ns = p_td.my_module->get_controlns();\n"
" type_atr = mcopystr(\" \");\n"
- " type_atr = mputstr (type_atr, control_ns->px);\n"
- " type_atr = mputstr (type_atr, \":type='\");\n"
- " type_atr = mputstrn(type_atr, type_name, name_len);\n"
- " type_atr = mputc (type_atr, '\\'');\n"
+ " type_atr = mputstr(type_atr, control_ns->px);\n"
+ " type_atr = mputstr(type_atr, \":type='\");\n"
+ " type_atr = mputstr(type_atr, type_name);\n"
+ " type_atr = mputc (type_atr, '\\'');\n"
+ " Free(type_name);\n"
" }\n"
" break;\n"
" default: break;\n"
src = mputprintf(src, " case %s_%s:\n"
" ec_1.set_msg(\"%s': \");\n"
" field_%s->XER_encode(%s_xer_, p_buf, flavor_0, "
- "p_indent + (!p_indent || !omit_tag));\n"
+ "p_indent + (!p_indent || !omit_tag), 0);\n"
" break;\n",
selection_prefix, sdef->elements[i].name,
sdef->elements[i].dispname,
def = mputstr(def,
"int XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
"const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
- "unsigned int p_flavor, int p_indent) const;\n");
+ "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const;\n");
src = mputprintf(src, /* XERSTUFF XER_encode for union */
"int %s::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
"const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
- "unsigned int p_flavor, int p_indent) const\n"
+ "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n"
"{\n"
" if (%s==union_selection) {\n"
" TTCN_error(\"Attempt to XER-encode an unbound union value.\");\n"
src = mputstr(src,
" const boolean e_xer = is_exer(p_flavor);\n"
" char *type_atr = NULL;\n"
- " unsigned short name_len = 0;\n"
" if (e_xer && (p_td.xer_bits & USE_TYPE_ATTR)) {\n"
- " const char *type_name = 0;\n"
+ " char *type_name = 0;\n"
" const namespace_t *control_ns;\n"
" switch (union_selection) {\n");
int start_at = sdef->xerUseUnion ? 0 : 1;
for (i = start_at; i < sdef->nElements; i++) {
src = mputprintf(src,
" case %s_%s:\n"
- " type_name = %s_xer_.names[1];\n"
- " name_len = %s_xer_.namelens[1] - 2;\n"
+ " if (%s_xer_.my_module != 0 && %s_xer_.ns_index != -1 &&\n"
+ " %s_xer_.namelens[1] > 2) {\n"
+ /* add the namespace prefix to the type attribute (if the name is not empty) */
+ " const namespace_t *my_ns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
+ " if (my_ns->px[0] != 0) {\n"
+ " type_name = mprintf(\"%%s:\", my_ns->px);\n"
+ " }\n"
+ " }\n"
+ " type_name = mputstrn(type_name, %s_xer_.names[1], %s_xer_.namelens[1] - 2);\n"
" %s\n"
, selection_prefix, sdef->elements[i].name
- , sdef->elements[i].typegen
+ , sdef->elements[i].typegen, sdef->elements[i].typegen
+ , sdef->elements[i].typegen, sdef->elements[i].typegen
+ , sdef->elements[i].typegen, sdef->elements[i].typegen
, sdef->elements[i].typegen
, i < sdef->nElements - 1 ? "goto write_atr;" : "" /* no break */
);
}
src = mputprintf(src,
"%s" /* label only if more than two elements total */
- " if (name_len > 0) {\n" /* 38.3.8, no atr if NAME AS "" */
+ " if (mstrlen(type_name) > 0) {\n" /* 38.3.8, no atr if NAME AS "" */
" control_ns = p_td.my_module->get_controlns();\n"
" type_atr = mcopystr(\" \");\n"
- " type_atr = mputstr (type_atr, control_ns->px);\n"
- " type_atr = mputstr (type_atr, \":type='\");\n"
- " type_atr = mputstrn(type_atr, type_name, name_len);\n"
- " type_atr = mputc (type_atr, '\\'');\n"
+ " type_atr = mputstr(type_atr, control_ns->px);\n"
+ " type_atr = mputstr(type_atr, \":type='\");\n"
+ " type_atr = mputstr(type_atr, type_name);\n"
+ " type_atr = mputc (type_atr, '\\'');\n"
+ " Free(type_name);\n"
" }\n"
" break;\n"
" default: break;\n"
"(\"internal error: erroneous value typedescriptor missing\");\n"
" else err_vals->value->errval->XER_encode("
"*err_vals->value->type_descr->xer, p_buf, flavor_0, "
- "p_indent + (!p_indent || !omit_tag));\n"
+ "p_indent + (!p_indent || !omit_tag), 0);\n"
" }\n"
" }\n"
" } else {\n"
" ec_1.set_msg(\"%s': \");\n"
" if (emb_descr) field_%s->XER_encode_negtest(emb_descr, "
- "%s_xer_, p_buf, flavor_0, p_indent + (!p_indent || !omit_tag));\n"
+ "%s_xer_, p_buf, flavor_0, p_indent + (!p_indent || !omit_tag), 0);\n"
" else field_%s->XER_encode(%s_xer_, p_buf, flavor_0, "
- "p_indent + (!p_indent || !omit_tag));\n"
+ "p_indent + (!p_indent || !omit_tag), 0);\n"
" }\n"
" break;\n",
selection_prefix, sdef->elements[i].name, /* case label */
#endif
src = mputprintf(src, /* XERSTUFF decoder functions for union */
"int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader,"
- " unsigned int p_flavor)\n"
+ " unsigned int p_flavor, unsigned int p_flavor2, embed_values_dec_struct_t*)\n"
"{\n"
" int e_xer = is_exer(p_flavor);\n"
" int type = 0;\n" /* None */
/* USE-TYPE: No type attribute means the first alternative */
src = mputprintf(src,
" if (typeatr == NULL) {\n"
- " typeatr = mcopystr(%s_xer_.names[1]);\n"
- " typeatr = mtruncstr(typeatr, %s_xer_.namelens[1] - 2);\n"
+ " typeatr = mcopystrn(%s_xer_.names[1], %s_xer_.namelens[1] - 2);\n"
" }\n"
, sdef->elements[0].typegen
, sdef->elements[0].typegen);
if (sdef->xerUseTypeAttr) {
src = mputstr(src,
" if (e_xer) {\n" /* USE-TYPE => no XML element, use typeatr */
- " elem_name = typeatr;\n"
+ " char *token_1 = strtok(typeatr, \":\");\n" /* extract the namespace (if any) */
+ " char *token_2 = strtok(NULL, \":\");\n"
+ " if (token_2) {\n" /* namespace found */
+ " elem_name = token_2;\n"
+ " ns_uri = get_ns_uri_from_prefix(token_1, p_td);\n"
+ " }\n"
+ " else {\n" /* no namespace */
+ " elem_name = token_1;\n"
+ " }\n"
" flavor_1 |= USE_TYPE_ATTR;\n"
" }\n"
" else" /* no newline, gobbles up the next {} */);
" ec_2.set_msg(\"%s': \");\n"
" if (%s==union_selection) {\n"
" matched = %d;\n"
- " %s().XER_decode(%s_xer_, p_reader, flavor_1);\n"
+ " %s().XER_decode(%s_xer_, p_reader, flavor_1, p_flavor2, 0);\n"
" }\n"
" if (field_%s->is_bound()) break; else clean_up();\n"
" }\n",
src = mputprintf(src,
" %sif (%s::can_start(elem_name, ns_uri, %s_xer_, flavor_1) || (%s_xer_.xer_bits & ANY_ELEMENT)) {\n"
" ec_2.set_msg(\"%s': \");\n"
- " %s%s().XER_decode(%s_xer_, p_reader, flavor_1);\n"
+ " if (e_xer && (%s_xer_.xer_bits & BLOCKED)) {\n"
+ " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
+ " \"Attempting to decode blocked or abstract field.\");\n"
+ " }\n"
+ " %s%s().XER_decode(%s_xer_, p_reader, flavor_1, p_flavor2, 0);\n"
" if (!%s%s().is_bound()) {\n"
" TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, \"Failed to decode field.\");\n"
" }\n"
i && !(i==1 && sdef->exerMaybeEmptyIndex==0) ? "else " : "", /* print "if(" if generate code for the first field or if the first field is the MaybeEmpty field and we generate the code for the second one*/
sdef->elements[i].type, sdef->elements[i].typegen, sdef->elements[i].typegen,
sdef->elements[i].dispname,
+ sdef->elements[i].typegen,
at_field, sdef->elements[i].name, sdef->elements[i].typegen,
at_field, sdef->elements[i].name);
}
src = mputprintf(src,
" %sif ((e_xer && (type==XML_READER_TYPE_END_ELEMENT || !own_tag)) || %s::can_start(elem_name, ns_uri, %s_xer_, flavor_1) || (%s_xer_.xer_bits & ANY_ELEMENT)) {\n"
"empty_xml: ec_2.set_msg(\"%s': \");\n"
- " %s%s().XER_decode(%s_xer_, p_reader, flavor_1);\n"
+ " if (e_xer && (%s_xer_.xer_bits & BLOCKED)) {\n"
+ " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
+ " \"Attempting to decode blocked or abstract field.\");\n"
+ " }\n"
+ " %s%s().XER_decode(%s_xer_, p_reader, flavor_1, p_flavor2, 0);\n"
" if (!%s%s().is_bound()) {\n"
" TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, \"Failed to decode field.\");\n"
" }\n"
sdef->nElements>0 ? "else " : "",
sdef->elements[i].type, sdef->elements[i].typegen, sdef->elements[i].typegen,
sdef->elements[i].dispname,
+ sdef->elements[i].typegen,
at_field, sdef->elements[i].name, sdef->elements[i].typegen,
at_field, sdef->elements[i].name);
}
- src = mputstr(src,
- " else {\n"
- " ec_1.set_msg(\" \");\n"
- " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
- "\"'%s' does not match any alternative\", elem_name);\n"
- " if (xml_depth >= 0) for (; rd_ok == 1 "
- "&& p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
- " }\n"
- );
+ if (!sdef->isOptional) {
+ src = mputstr(src,
+ " else {\n"
+ " ec_1.set_msg(\" \");\n"
+ " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
+ "\"'%s' does not match any alternative\", elem_name);\n"
+ " if (xml_depth >= 0) for (; rd_ok == 1 "
+ "&& p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
+ " }\n"
+ );
+ }
}
src = mputprintf(src,
if (json_needed) {
// JSON encode
src = mputprintf(src,
- "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
- "{\n", name);
+ "int %s::JSON_encode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok) const\n"
+ "{\n", name, use_runtime_2 ? " p_td" : "");
+ if (use_runtime_2) {
+ src = mputstr(src, " if (err_descr) return JSON_encode_negtest(err_descr, p_td, p_tok);\n");
+ }
if (!sdef->jsonAsValue) {
src = mputstr(src, " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n");
} else {
" return enc_len;\n"
"}\n\n");
+ if (use_runtime_2) {
+ // JSON encode for negative testing
+ def = mputstr(def,
+ "int JSON_encode_negtest(const Erroneous_descriptor_t*, "
+ "const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;\n");
+ src = mputprintf(src,
+ "int %s::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
+ "const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
+ "{\n", name);
+ if (!sdef->jsonAsValue) {
+ src = mputstr(src, " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n");
+ } else {
+ src = mputstr(src, " int enc_len = 0;\n\n");
+ }
+ src = mputstr(src,
+ " const Erroneous_values_t* err_vals = NULL;\n"
+ " const Erroneous_descriptor_t* emb_descr = NULL;\n"
+ " switch(union_selection) {\n");
+
+ for (i = 0; i < sdef->nElements; ++i) {
+ src = mputprintf(src,
+ " case %s_%s:\n"
+ " err_vals = p_err_descr->get_field_err_values(%d);\n"
+ " emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
+ " if (NULL != err_vals && NULL != err_vals->value) {\n"
+ " if (NULL != err_vals->value->errval) {\n"
+ " if(err_vals->value->raw){\n"
+ " enc_len += err_vals->value->errval->JSON_encode_negtest_raw(p_tok);\n"
+ " } else {\n"
+ " if (NULL == err_vals->value->type_descr) {\n"
+ " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
+ " }\n"
+ , selection_prefix, sdef->elements[i].name, (int)i, (int)i);
+ if (!sdef->jsonAsValue) {
+ src = mputprintf(src, " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+ , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
+ }
+ src = mputstr(src,
+ " enc_len += err_vals->value->errval->JSON_encode(*err_vals->value->type_descr, p_tok);\n"
+ " }\n"
+ " }\n"
+ " } else {\n");
+ if (!sdef->jsonAsValue) {
+ src = mputprintf(src, " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
+ , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
+ }
+ src = mputprintf(src,
+ " if (NULL != emb_descr) {\n"
+ " enc_len += field_%s->JSON_encode_negtest(emb_descr, %s_descr_, p_tok);\n"
+ " } else {\n"
+ " enc_len += field_%s->JSON_encode(%s_descr_, p_tok);\n"
+ " }\n"
+ " }\n"
+ " break;\n"
+ , sdef->elements[i].name, sdef->elements[i].typedescrname
+ , 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);
+ if (!sdef->jsonAsValue) {
+ src = mputstr(src, " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n");
+ }
+ src = mputstr(src,
+ " return enc_len;\n"
+ "}\n\n");
+ }
+
// JSON decode
src = mputprintf(src,
- "int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)\n"
+ "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
"{\n"
- " json_token_t token = JSON_TOKEN_NONE;\n"
+ " json_token_t j_token = JSON_TOKEN_NONE;\n"
, name);
if (sdef->jsonAsValue) {
src = mputstr(src,
" size_t buf_pos = p_tok.get_buf_pos();\n"
- " p_tok.get_next_token(&token, NULL, NULL);\n"
+ " p_tok.get_next_token(&j_token, NULL, NULL);\n"
" int ret_val = 0;\n"
- " switch(token) {\n"
+ " switch(j_token) {\n"
" case JSON_TOKEN_NUMBER: {\n");
for (i = 0; i < sdef->nElements; ++i) {
if (JSON_NUMBER & sdef->elements[i].jsonValueType) {
" return JSON_ERROR_FATAL;\n"
" }\n"
" case JSON_TOKEN_LITERAL_TRUE:\n"
- " case JSON_TOKEN_LITERAL_FALSE:\n"
- " case JSON_TOKEN_LITERAL_NULL: {\n");
+ " case JSON_TOKEN_LITERAL_FALSE: {\n");
for (i = 0; i < sdef->nElements; ++i) {
- if (JSON_LITERAL & sdef->elements[i].jsonValueType) {
+ if (JSON_BOOLEAN & sdef->elements[i].jsonValueType) {
src = mputprintf(src,
" p_tok.set_buf_pos(buf_pos);\n"
" ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
}
}
src = mputstr(src,
- " char* literal = mprintf(\"literal (%s)\",\n"
- " (JSON_TOKEN_LITERAL_TRUE == token) ? \"true\" :\n"
- " ((JSON_TOKEN_LITERAL_FALSE == token) ? \"false\" : \"null\"));\n"
- " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, literal);\n"
- " Free(literal);\n"
+ " char* literal_str = mprintf(\"literal (%s)\",\n"
+ " (JSON_TOKEN_LITERAL_TRUE == j_token) ? \"true\" : \"false\");\n"
+ " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, literal_str);\n"
+ " Free(literal_str);\n"
" clean_up();\n"
" return JSON_ERROR_FATAL;\n"
" }\n"
" clean_up();\n"
" return JSON_ERROR_FATAL;\n"
" }\n"
+ " case JSON_TOKEN_LITERAL_NULL: {\n");
+ for (i = 0; i < sdef->nElements; ++i) {
+ if (JSON_NULL & sdef->elements[i].jsonValueType) {
+ src = mputprintf(src,
+ " p_tok.set_buf_pos(buf_pos);\n"
+ " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
+ " if (0 <= ret_val) {\n"
+ " return ret_val;\n"
+ " }\n"
+ , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
+ }
+ }
+ src = mputstr(src,
+ " clean_up();\n"
+ // the caller might be able to decode the null value if it's an optional field
+ // only return an invalid token error, not a fatal error
+ " return JSON_ERROR_INVALID_TOKEN;\n"
+ " }\n"
" case JSON_TOKEN_ERROR:\n"
" JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
" return JSON_ERROR_FATAL;\n"
"}\n\n");
} else { // not "as value"
src = mputprintf(src,
- " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
- " if (JSON_TOKEN_ERROR == token) {\n"
+ " int dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
+ " if (JSON_TOKEN_ERROR == j_token) {\n"
" JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
" return JSON_ERROR_FATAL;\n"
" }\n"
- " else if (JSON_TOKEN_OBJECT_START != token) {\n"
+ " else if (JSON_TOKEN_OBJECT_START != j_token) {\n"
" return JSON_ERROR_INVALID_TOKEN;\n"
" }\n\n"
- " char* name = 0;\n"
- " size_t name_len = 0;"
- " dec_len += p_tok.get_next_token(&token, &name, &name_len);\n"
- " if (JSON_TOKEN_NAME != token) {\n"
+ " char* fld_name = 0;\n"
+ " size_t name_len = 0;\n"
+ " dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n"
+ " if (JSON_TOKEN_NAME != j_token) {\n"
" JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n"
" return JSON_ERROR_FATAL;\n"
" } else {\n"
, unbound_value);
for (i = 0; i < sdef->nElements; ++i) {
src = mputprintf(src,
- "if (0 == strncmp(name, \"%s\", name_len)) {\n"
+ "if (0 == strncmp(fld_name, \"%s\", name_len)) {\n"
" int ret_val = %s%s().JSON_decode(%s_descr_, p_tok, p_silent);\n"
" if (0 > ret_val) {\n"
" if (JSON_ERROR_INVALID_TOKEN) {\n"
}
src = mputstr(src,
"{\n"
- " char* name2 = mcopystrn(name, name_len);\n"
- " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, name2);\n"
- " Free(name2);\n"
+ " char* fld_name2 = mcopystrn(fld_name, name_len);\n"
+ " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, fld_name2);\n"
+ " Free(fld_name2);\n"
" return JSON_ERROR_FATAL;\n"
" }\n"
" }\n\n"
- " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n"
- " if (JSON_TOKEN_OBJECT_END != token) {\n"
+ " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
+ " if (JSON_TOKEN_OBJECT_END != j_token) {\n"
" JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n"
" return JSON_ERROR_FATAL;\n"
" }\n\n"
"}\n\n", name, name, name);
/* match function */
- def = mputprintf(def, "boolean match(const %s& other_value) const;\n", name);
- src = mputprintf(src, "boolean %s_template::match(const %s& other_value) "
- "const\n"
+ def = mputprintf(def, "boolean match(const %s& other_value, boolean legacy "
+ "= FALSE) const;\n", name);
+ src = mputprintf(src, "boolean %s_template::match(const %s& other_value, "
+ "boolean legacy) const\n"
"{\n"
"if (!other_value.is_bound()) return FALSE;\n"
"switch (template_selection) {\n"
"switch (value_selection) {\n", name, name, selection_type, unbound_value);
for (i = 0; i < sdef->nElements; i++) {
src = mputprintf(src, "case %s_%s:\n"
- "return single_value.field_%s->match(other_value.%s%s());\n",
+ "return single_value.field_%s->match(other_value.%s%s(), legacy);\n",
selection_prefix, sdef->elements[i].name, sdef->elements[i].name,
at_field, sdef->elements[i].name);
}
"case COMPLEMENTED_LIST:\n"
"for (unsigned int list_count = 0; list_count < value_list.n_values; "
"list_count++)\n"
- "if (value_list.list_value[list_count].match(other_value)) "
+ "if (value_list.list_value[list_count].match(other_value, legacy)) "
"return template_selection == VALUE_LIST;\n"
"return template_selection == COMPLEMENTED_LIST;\n"
"default:\n"
"void copy_value(const Base_Type* other_value);\n"
"Base_Template* clone() const;\n"
"const TTCN_Typedescriptor_t* get_descriptor() const;\n"
- "boolean matchv(const Base_Type* other_value) const;\n"
- "void log_matchv(const Base_Type* match_value) const;\n");
+ "boolean matchv(const Base_Type* other_value, boolean legacy) const;\n"
+ "void log_matchv(const Base_Type* match_value, boolean legacy) const;\n");
src = mputprintf(src,
"void %s_template::valueofv(Base_Type* value) const "
"{ *(static_cast<%s*>(value)) = valueof(); }\n"
"{ return new %s_template(*this); }\n"
"const TTCN_Typedescriptor_t* %s_template::get_descriptor() const "
"{ return &%s_descr_; }\n"
- "boolean %s_template::matchv(const Base_Type* other_value) const "
- "{ return match(*(static_cast<const %s*>(other_value))); }\n"
- "void %s_template::log_matchv(const Base_Type* match_value) const "
- " { log_match(*(static_cast<const %s*>(match_value))); }\n",
+ "boolean %s_template::matchv(const Base_Type* other_value, "
+ "boolean legacy) const "
+ "{ return match(*(static_cast<const %s*>(other_value)), legacy); }\n"
+ "void %s_template::log_matchv(const Base_Type* match_value, "
+ "boolean legacy) const "
+ " { log_match(*(static_cast<const %s*>(match_value)), legacy); }\n",
name, name,
name,
name, name,
src = mputstr(src, "}\n\n");
/* log_match function */
- def = mputprintf(def, "void log_match(const %s& match_value) "
- "const;\n", name);
+ def = mputprintf(def, "void log_match(const %s& match_value, "
+ "boolean legacy = FALSE) const;\n", name);
src = mputprintf(src,
- "void %s_template::log_match(const %s& match_value) const\n"
+ "void %s_template::log_match(const %s& match_value, boolean legacy) const\n"
"{\n"
- "if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity() && match(match_value)){\n"
+ "if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity() "
+ "&& match(match_value, legacy)){\n"
"TTCN_Logger::print_logmatch_buffer();\n"
"TTCN_Logger::log_event_str(\" matched\");\n"
"return;\n"
src = mputprintf(src, "case %s_%s:\n"
"if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){\n"
"TTCN_Logger::log_logmatch_info(\".%s\");\n"
- "single_value.field_%s->log_match(match_value.%s%s());\n"
+ "single_value.field_%s->log_match(match_value.%s%s(), legacy);\n"
"} else {\n"
"TTCN_Logger::log_event_str(\"{ %s := \");\n"
- "single_value.field_%s->log_match(match_value.%s%s());\n"
+ "single_value.field_%s->log_match(match_value.%s%s(), legacy);\n"
"TTCN_Logger::log_event_str(\" }\");\n"
"}\n"
"break;\n", selection_prefix, sdef->elements[i].name,
"match_value.log();\n"
"TTCN_Logger::log_event_str(\" with \");\n"
"log();\n"
- "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n"
+ "if (match(match_value, legacy)) TTCN_Logger::log_event_str(\" matched\");\n"
"else TTCN_Logger::log_event_str(\" unmatched\");\n"
"}\n"
"}\n\n");
"}\n\n", dispname, name, dispname);
/* TTCN-3 ispresent() function */
- def = mputstr(def, "boolean is_present() const;\n");
+ def = mputstr(def, "boolean is_present(boolean legacy = FALSE) const;\n");
src = mputprintf(src,
- "boolean %s_template::is_present() const\n"
+ "boolean %s_template::is_present(boolean legacy) const\n"
"{\n"
"if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n"
- "return !match_omit();\n"
+ "return !match_omit(legacy);\n"
"}\n\n", name);
/* match_omit() */
- def = mputstr(def, "boolean match_omit() const;\n");
+ def = mputstr(def, "boolean match_omit(boolean legacy = FALSE) const;\n");
src = mputprintf(src,
- "boolean %s_template::match_omit() const\n"
+ "boolean %s_template::match_omit(boolean legacy) const\n"
"{\n"
"if (is_ifpresent) return TRUE;\n"
"switch (template_selection) {\n"
"return TRUE;\n"
"case VALUE_LIST:\n"
"case COMPLEMENTED_LIST:\n"
+ "if (legacy) {\n"
"for (unsigned int v_idx=0; v_idx<value_list.n_values; v_idx++)\n"
"if (value_list.list_value[v_idx].match_omit())\n"
"return template_selection==VALUE_LIST;\n"
"return template_selection==COMPLEMENTED_LIST;\n"
+ "} // else fall through\n"
"default:\n"
"return FALSE;\n"
"}\n"
"param.error(\"Field `%%s' not found in union template type `%s'\", param_field);\n"
" }\n"
" param.basic_check(Module_Param::BC_TEMPLATE, \"union template\");\n"
- " switch (param.get_type()) {\n"
+ " Module_Param_Ptr m_p = ¶m;\n"
+ " if (param.get_type() == Module_Param::MP_Reference) {\n"
+ " m_p = param.get_referenced_param();\n"
+ " }\n"
+ " switch (m_p->get_type()) {\n"
" case Module_Param::MP_Omit:\n"
" *this = OMIT_VALUE;\n"
" break;\n"
" *this = ANY_OR_OMIT;\n"
" break;\n"
" case Module_Param::MP_List_Template:\n"
- " case Module_Param::MP_ComplementList_Template:\n"
- " set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());\n"
- " for (size_t p_i=0; p_i<param.get_size(); p_i++) {\n"
- " list_item(p_i).set_param(*param.get_elem(p_i));\n"
+ " case Module_Param::MP_ComplementList_Template: {\n"
+ " %s_template new_temp;\n"
+ " new_temp.set_type(m_p->get_type()==Module_Param::MP_List_Template ? "
+ "VALUE_LIST : COMPLEMENTED_LIST, m_p->get_size());\n"
+ " for (size_t p_i=0; p_i<m_p->get_size(); p_i++) {\n"
+ " new_temp.list_item(p_i).set_param(*m_p->get_elem(p_i));\n"
" }\n"
- " break;\n"
+ " *this = new_temp;\n"
+ " break; }\n"
" case Module_Param::MP_Value_List:\n"
- " if (param.get_size()==0) break;\n" /* for backward compatibility */
+ " if (m_p->get_size()==0) break;\n" /* for backward compatibility */
" param.type_error(\"union template\", \"%s\");\n"
" break;\n"
" case Module_Param::MP_Assignment_List: {\n"
- " Module_Param* mp_last = param.get_elem(param.get_size()-1);\n",
- dispname, dispname);
+ " Module_Param* mp_last = m_p->get_elem(m_p->get_size()-1);\n",
+ dispname, name, dispname);
for (i = 0; i < sdef->nElements; i++) {
src = mputprintf(src,
" if (!strcmp(mp_last->get_id()->get_name(), \"%s\")) {\n"
" default:\n"
" param.type_error(\"union template\", \"%s\");\n"
" }\n"
- " is_ifpresent = param.get_ifpresent();\n"
+ " is_ifpresent = param.get_ifpresent() || m_p->get_ifpresent();\n"
"}\n\n", dispname, dispname);
+
+ /* get_param() */
+ def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
+ src = mputprintf(src,
+ "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n"
+ "{\n"
+ " if (param_name.next_name()) {\n"
+ // Haven't reached the end of the module parameter name
+ // => the name refers to one of the fields, not to the whole union
+ " char* param_field = param_name.get_current_name();\n"
+ " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
+ " TTCN_error(\"Unexpected array index in module parameter reference, \"\n"
+ " \"expected a valid field name for union template type `%s'\");\n"
+ " }\n"
+ " ", name, dispname);
+ for (i = 0; i < sdef->nElements; i++) {
+ src = mputprintf(src,
+ "if (strcmp(\"%s\", param_field) == 0) {\n"
+ " return %s%s().get_param(param_name);\n"
+ " } else ",
+ sdef->elements[i].dispname, at_field, sdef->elements[i].name);
+ }
+ src = mputprintf(src,
+ "TTCN_error(\"Field `%%s' not found in union type `%s'\", param_field);\n"
+ " }\n"
+ " Module_Param* m_p = NULL;\n"
+ " switch (template_selection) {\n"
+ " case UNINITIALIZED_TEMPLATE:\n"
+ " m_p = new Module_Param_Unbound();\n"
+ " break;\n"
+ " case OMIT_VALUE:\n"
+ " m_p = new Module_Param_Omit();\n"
+ " break;\n"
+ " case ANY_VALUE:\n"
+ " m_p = new Module_Param_Any();\n"
+ " break;\n"
+ " case ANY_OR_OMIT:\n"
+ " m_p = new Module_Param_AnyOrNone();\n"
+ " break;\n"
+ " case SPECIFIC_VALUE: {\n"
+ " Module_Param* mp_field = NULL;\n"
+ " switch(single_value.union_selection) {\n"
+ , name);
+ for (i = 0; i < sdef->nElements; ++i) {
+ src = mputprintf(src,
+ " case %s_%s:\n"
+ " mp_field = single_value.field_%s->get_param(param_name);\n"
+ " mp_field->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n"
+ " break;\n"
+ , selection_prefix, sdef->elements[i].name
+ , sdef->elements[i].name, sdef->elements[i].dispname);
+ }
+ src = mputstr(src,
+ " default:\n"
+ " break;\n"
+ " }\n"
+ " m_p = new Module_Param_Assignment_List();\n"
+ " m_p->add_elem(mp_field);\n"
+ " break; }\n"
+ " case VALUE_LIST:\n"
+ " case COMPLEMENTED_LIST: {\n"
+ " if (template_selection == VALUE_LIST) {\n"
+ " m_p = new Module_Param_List_Template();\n"
+ " }\n"
+ " else {\n"
+ " m_p = new Module_Param_ComplementList_Template();\n"
+ " }\n"
+ " for (size_t i_i = 0; i_i < value_list.n_values; ++i_i) {\n"
+ " m_p->add_elem(value_list.list_value[i_i].get_param(param_name));\n"
+ " }\n"
+ " break; }\n"
+ " default:\n"
+ " break;\n"
+ " }\n"
+ " if (is_ifpresent) {\n"
+ " m_p->set_ifpresent();\n"
+ " }\n"
+ " return m_p;\n"
+ "}\n\n");
/* check template restriction */
def = mputstr(def, "void check_restriction(template_res t_res, "
- "const char* t_name=NULL) const;\n");
+ "const char* t_name=NULL, boolean legacy = FALSE) const;\n");
src = mputprintf(src,
"void %s_template::check_restriction("
- "template_res t_res, const char* t_name) const\n"
+ "template_res t_res, const char* t_name, boolean legacy) const\n"
"{\n"
"if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
"switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
"performing check_restriction operation on a template of union type %s.\");\n"
"}\n"
"case TR_PRESENT:\n"
- "if (!match_omit()) return;\n"
+ "if (!match_omit(legacy)) return;\n"
"break;\n"
"default:\n"
"return;\n"