-///////////////////////////////////////////////////////////////////////////////
-// 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
+ * Delic, Adam
+ * Raduly, Csaba
+ * Szabados, Kristof
+ * Pandi, Krisztian
+ *
+ ******************************************************************************/
#include "../common/dbgnew.hh"
#include "Type.hh"
#include "CompField.hh"
int atrib=0, any_atr=0, any_elem=0, base64=0, decimal=0, embed=0, list=0,
text=0, untagged=0, use_nil=0, use_number=0, use_order=0, use_qname=0,
use_type_attr=0, ws=0, has_1untag=0, form_qualified=0, any_from=0,
- any_except=0, nof_ns_uris=0;
+ any_except=0, nof_ns_uris=0, blocked=0;
const char* dfe_str = 0;
char** ns_uris = 0;
char* oftype_descr_name = 0;
any_elem= has_ae(xerattrib);
atrib = xerattrib->attribute_;
base64 = xerattrib->base64_;
+ blocked = xerattrib->abstract_ || xerattrib->block_;
decimal = xerattrib->decimal_;
embed = xerattrib->embedValues_;
form_qualified = (xerattrib->form_ & XerAttributes::QUALIFIED)
// Generate the XER descriptor itself
target->source.global_vars = mputprintf(target->source.global_vars,
"const XERdescriptor_t %s_xer_ = { {\"%s>\\n\", \"%s>\\n\"},"
- " {%lu, %lu}, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s, WHITESPACE_%s, %c%s, "
+ " {%lu, %lu}, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s, WHITESPACE_%s, %c%s, "
"&%s, %ld, %u, %s, %s };\n",
gennameown_str,
bxer_name.c_str(), last_s.c_str(), // names
(any_elem ? " |ANY_ELEMENT" : ""),
(atrib ? " |XER_ATTRIBUTE" : ""),
(base64 ? " |BASE_64" : ""),
+ (blocked ? " |BLOCKED" : ""),
(decimal ? " |XER_DECIMAL" : ""),
(embed ? " |EMBED_VALUES" : ""),
(list ? " |XER_LIST" : ""),
(form_qualified ? "" : " |FORM_UNQUALIFIED"),
(any_from ? " |ANY_FROM" : ""),
(any_except ? " |ANY_EXCEPT" : ""),
+ (is_optional_field() ? " |XER_OPTIONAL" : ""),
whitespace_action[ws],
(dfe_str ? '&' : ' '), (dfe_str ? dfe_str : "NULL"),
"module_object",
"extern const TTCN_RAWdescriptor_t %s_raw_;\n", gennameown_str);
char *str = mprintf("const TTCN_RAWdescriptor_t %s_raw_ = {",
gennameown_str);
- str = mputprintf(str, "%d,", rawattrib->fieldlength);
+ if (rawattrib->intx) {
+ str = mputstr(str, "RAW_INTX,");
+ }
+ else {
+ str = mputprintf(str, "%d,", rawattrib->fieldlength);
+ }
if (rawattrib->comp == XDEFCOMPL) str = mputstr(str, "SG_2COMPL,");
else if (rawattrib->comp == XDEFSIGNBIT) str = mputstr(str, "SG_SG_BIT,");
else str = mputstr(str, "SG_NO,");
if (NULL == jsonattrib) {
target->source.global_vars = mputprintf(target->source.global_vars,
- "const TTCN_JSONdescriptor_t %s_json_ = { false, NULL, false, NULL };\n"
+ "const TTCN_JSONdescriptor_t %s_json_ = { false, NULL, false, NULL, false };\n"
, get_genname_own().c_str());
} else {
char* alias = jsonattrib->alias ? mputprintf(NULL, "\"%s\"", jsonattrib->alias) : NULL;
char* def_val = jsonattrib->default_value ?
mputprintf(NULL, "\"%s\"", jsonattrib->default_value) : NULL;
target->source.global_vars = mputprintf(target->source.global_vars,
- "const TTCN_JSONdescriptor_t %s_json_ = { %s, %s, %s, %s };\n"
+ "const TTCN_JSONdescriptor_t %s_json_ = { %s, %s, %s, %s, %s };\n"
, get_genname_own().c_str()
, jsonattrib->omit_as_null ? "true" : "false"
, alias ? alias : "NULL"
, jsonattrib->as_value ? "true" : "false"
- , def_val ? def_val : "NULL");
+ , def_val ? def_val : "NULL"
+ , jsonattrib->metainfo_unbound ? "true" : "false");
Free(alias);
Free(def_val);
}
sdef.opentype_outermost = get_is_opentype_outermost();
sdef.ot = generate_code_ot(pool);
sdef.nElements = get_nof_comps();
+ sdef.isOptional = false;
+ if (parent_type != NULL) {
+ switch (parent_type->typetype) {
+ case T_SEQ_T:
+ case T_SEQ_A:
+ case T_SET_T:
+ case T_SET_A:
+ for (size_t x = 0; x < parent_type->get_nof_comps(); ++x) {
+ CompField * cf = parent_type->get_comp_byIndex(x);
+ if (cf->get_type() == this && cf->get_is_optional()) {
+ sdef.isOptional = true;
+ break; // from the for loop
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
sdef.elements = (struct_field*)
Malloc(sdef.nElements*sizeof(*sdef.elements));
memset(sdef.elements, 0, sdef.nElements*sizeof(*sdef.elements));
typetype_t tt = cftype->get_type_refd_last()->typetype;
switch(tt) {
case T_INT:
+ case T_INT_A:
sdef.elements[i].jsonValueType = JSON_NUMBER;
break;
case T_REAL:
sdef.elements[i].jsonValueType = JSON_NUMBER | JSON_STRING;
break;
case T_BOOL:
- sdef.elements[i].jsonValueType = JSON_LITERAL;
+ sdef.elements[i].jsonValueType = JSON_BOOLEAN;
+ break;
+ case T_NULL:
+ sdef.elements[i].jsonValueType = JSON_NULL;
break;
case T_BSTR:
+ case T_BSTR_A:
case T_HSTR:
case T_OSTR:
case T_CSTR:
case T_USTR:
+ case T_UTF8STRING:
+ case T_NUMERICSTRING:
+ case T_PRINTABLESTRING:
+ case T_TELETEXSTRING:
+ case T_VIDEOTEXSTRING:
+ case T_IA5STRING:
+ case T_GRAPHICSTRING:
+ case T_VISIBLESTRING:
+ case T_GENERALSTRING:
+ case T_UNIVERSALSTRING:
+ case T_BMPSTRING:
case T_VERDICT:
case T_ENUM_T:
+ case T_ENUM_A:
+ case T_OID:
+ case T_ROID:
+ case T_ANY:
sdef.elements[i].jsonValueType = JSON_STRING;
break;
case T_SEQ_T:
+ case T_SEQ_A:
case T_SET_T:
+ case T_SET_A:
case T_CHOICE_T:
+ case T_CHOICE_A:
+ case T_ANYTYPE:
+ case T_OPENTYPE:
sdef.elements[i].jsonValueType = JSON_OBJECT;
break;
case T_SEQOF:
case T_SETOF:
+ case T_ARRAY:
sdef.elements[i].jsonValueType = JSON_ARRAY;
break;
default:
cur.jsonOmitAsNull = type->jsonattrib->omit_as_null;
cur.jsonAlias = type->jsonattrib->alias;
cur.jsonDefaultValue = type->jsonattrib->default_value;
+ cur.jsonMetainfoUnbound = type->jsonattrib->metainfo_unbound;
} // if jsonattrib
} // next element
case T_UNIVERSALSTRING:
case T_BMPSTRING:
case T_OBJECTDESCRIPTOR:
- target->header.typedefs = mputprintf(target->header.typedefs,
+ target->header.class_decls = mputprintf(target->header.class_decls,
"typedef PreGenRecordOf::PREGEN__%s__OF__UNIVERSAL__CHARSTRING%s %s;\n"
"typedef PreGenRecordOf::PREGEN__%s__OF__UNIVERSAL__CHARSTRING%s_template %s_template;\n",
(typetype == T_SEQOF) ? "RECORD" : "SET",
optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str());
return;
default:
- target->header.typedefs = mputprintf(target->header.typedefs,
+ // generate these in the class declarations part, they need to be
+ // outside of the include guard in case of circular imports
+ target->header.class_decls = mputprintf(target->header.class_decls,
"typedef PreGenRecordOf::PREGEN__%s__OF__%s%s %s;\n"
"typedef PreGenRecordOf::PREGEN__%s__OF__%s%s_template %s_template;\n",
(typetype == T_SEQOF) ? "RECORD" : "SET", oftypename.c_str(),
}
fdef.runs_on_self = u.fatref.runs_on.self ? TRUE : FALSE;
fdef.is_startable = u.fatref.is_startable;
- fdef.formal_par_list = u.fatref.fp_list->generate_code(memptystr());
+ fdef.formal_par_list = u.fatref.fp_list->generate_code(memptystr(),
+ u.fatref.fp_list->get_nof_fps());
u.fatref.fp_list->generate_code_defval(target);
fdef.actual_par_list = u.fatref.fp_list
->generate_code_actual_parlist(memptystr(),"");
"component_reference.log();\n"
"TTCN_Logger::log_event_str(\" failed: Return value does not match "
"the template: \");\n"
- "value_template.log_match(return_value);\n"
+ "value_template.log_match(return_value%s);\n"
"TTCN_Logger::end_event();\n"
"}\n"
"return ALT_NO;\n"
"} else return ret_val;\n"
"}\n\n",
genname_str, genname_str, dispname_str, genname_str, dispname_str,
- dispname_str);
+ dispname_str, omit_in_value_list ? ", TRUE" : "");
}
bool Type::ispresent_anyvalue_embedded_field(Type* t,
is_template?"_template":"", tmp_id_str);
expr->expr = mputprintf(expr->expr,
- "%s = %s.%s();\n", global_id.c_str(),
- tmp_id2_str, isbound ? "is_bound" : "is_present");
+ "%s = %s.%s(%s);\n", global_id.c_str(),
+ tmp_id2_str, isbound ? "is_bound" : "is_present",
+ (!isbound && is_template && omit_in_value_list) ? "TRUE" : "");
Free(tmp_generalid_str);
tmp_generalid_str = mcopystr(tmp_id2_str);
id.get_name().c_str());
expr->expr = mputprintf(expr->expr,
- "%s = %s.%s();\n", global_id.c_str(),
- tmp_id_str, isbound||(i!=(nof_refs-1)) ? "is_bound" : "is_present");
+ "%s = %s.%s(%s);\n", global_id.c_str(),
+ tmp_id_str, isbound||(i!=(nof_refs-1)) ? "is_bound" : "is_present",
+ (!(isbound||(i!=(nof_refs-1))) && is_template && omit_in_value_list) ? "TRUE" : "");
Free(tmp_generalid_str);
tmp_generalid_str = mcopystr(tmp_id_str);
}
if (is_string_element) {
expr->expr = mputprintf(expr->expr,
- "%s = %s[%s].%s();\n", global_id.c_str(),
+ "%s = %s[%s].%s(%s);\n", global_id.c_str(),
tmp_generalid_str, tmp_index_id_str,
- isbound||(i!=(nof_refs-1)) ? "is_bound" : "is_present");
+ isbound||(i!=(nof_refs-1)) ? "is_bound" : "is_present",
+ (!(isbound||(i!=(nof_refs-1))) && is_template && omit_in_value_list) ? "TRUE" : "");
} else {
if (is_template) {
expr->expr = mputprintf(expr->expr,
}
expr->expr = mputprintf(expr->expr,
- "%s = %s.%s();\n", global_id.c_str(), tmp_id_str,
- isbound||(i!=(nof_refs-1)) ? "is_bound" : "is_present");
+ "%s = %s.%s(%s);\n", global_id.c_str(), tmp_id_str,
+ isbound||(i!=(nof_refs-1)) ? "is_bound" : "is_present",
+ (!(isbound||(i!=(nof_refs-1))) && is_template && omit_in_value_list) ? "TRUE" : "");
}
Free(tmp_generalid_str);
Free(alias_str);
}
}
-
+
// get the type at the end of the reference chain
Type* last = get_type_refd_last();
- // if the type has its own definition and it's embedded in another type, then
- // its schema already exists, only add a reference to it
+ // check if this is a reference to another type that has its own definition
+ Type* refd_type = NULL;
+ if (is_ref()) {
+ Type* iter = this;
+ while (iter->is_ref()) {
+ iter = iter->get_type_refd();
+ if (iter->ownertype == OT_TYPE_DEF || /* TTCN-3 type definition */
+ iter->ownertype == OT_TYPE_ASS) { /* ASN.1 type assignment */
+ refd_type = iter;
+ break;
+ }
+ }
+ }
+
+ // check if there are any type restrictions
+ boolean has_restrictions = sub_type != NULL && sub_type->has_json_schema();
+
+ // if it's a referenced type, then its schema already exists, only add a pointer to it
// exception: instances of ASN.1 parameterized types, always embed their schemas
- if (embedded && (!is_ref() || !get_type_refd()->pard_type_instance) &&
- (last->ownertype == OT_TYPE_DEF /* TTCN-3 type definition */
- || last->ownertype == OT_TYPE_ASS /* ASN.1 type assignment */ )) {
+ if (refd_type != NULL && !get_type_refd()->pard_type_instance) {
+ if (has_restrictions) {
+ // an 'allOf' structure is needed if this is a subtype,
+ // insert the pointer in the first part
+ json.put_next_token(JSON_TOKEN_NAME, "allOf");
+ json.put_next_token(JSON_TOKEN_ARRAY_START);
+ json.put_next_token(JSON_TOKEN_OBJECT_START);
+ }
json.put_next_token(JSON_TOKEN_NAME, "$ref");
char* ref_str = mprintf("\"#/definitions/%s/%s\"",
- last->my_scope->get_scope_mod()->get_modid().get_ttcnname().c_str(),
- (is_ref() && last->pard_type_instance) ? get_type_refd()->get_dispname().c_str() : last->get_dispname().c_str());
+ refd_type->my_scope->get_scope_mod()->get_modid().get_ttcnname().c_str(),
+ refd_type->get_dispname().c_str());
json.put_next_token(JSON_TOKEN_STRING, ref_str);
Free(ref_str);
+ if (has_restrictions) {
+ // close the first part of the 'allOf' and insert the type restrictions
+ // in the second part
+ json.put_next_token(JSON_TOKEN_OBJECT_END);
+ json.put_next_token(JSON_TOKEN_OBJECT_START);
+
+ // pass the tokenizer to the subtype to insert the type restrictions' schema
+ sub_type->generate_json_schema(json);
+
+ // close the second part and the 'allOf' structure itself
+ json.put_next_token(JSON_TOKEN_OBJECT_END);
+ json.put_next_token(JSON_TOKEN_ARRAY_END);
+ }
} else {
// generate the schema for the referenced type
switch (last->typetype) {
json.put_next_token(JSON_TOKEN_STRING, "\"integer\"");
break;
case T_REAL:
- // any of: JSON number or the special values as strings (in an enum)
- json.put_next_token(JSON_TOKEN_NAME, "anyOf");
- json.put_next_token(JSON_TOKEN_ARRAY_START);
- json.put_next_token(JSON_TOKEN_OBJECT_START);
- json.put_next_token(JSON_TOKEN_NAME, "type");
- json.put_next_token(JSON_TOKEN_STRING, "\"number\"");
- json.put_next_token(JSON_TOKEN_OBJECT_END);
- json.put_next_token(JSON_TOKEN_OBJECT_START);
- json.put_next_token(JSON_TOKEN_NAME, "enum");
- json.put_next_token(JSON_TOKEN_ARRAY_START);
- json.put_next_token(JSON_TOKEN_STRING, "\"not_a_number\"");
- json.put_next_token(JSON_TOKEN_STRING, "\"infinity\"");
- json.put_next_token(JSON_TOKEN_STRING, "\"-infinity\"");
- json.put_next_token(JSON_TOKEN_ARRAY_END);
- json.put_next_token(JSON_TOKEN_OBJECT_END);
- json.put_next_token(JSON_TOKEN_ARRAY_END);
+ if (has_restrictions) {
+ // adding restrictions after the type's schema wouldn't work here
+ // if the restrictions affect the special values
+ // use a special function that generates the schema segment for both
+ // the float type and its restrictions
+ sub_type->generate_json_schema_float(json);
+ has_restrictions = false; // so they aren't generated twice
+ }
+ else {
+ // any of: JSON number or the special values as strings (in an enum)
+ json.put_next_token(JSON_TOKEN_NAME, "anyOf");
+ json.put_next_token(JSON_TOKEN_ARRAY_START);
+ json.put_next_token(JSON_TOKEN_OBJECT_START);
+ json.put_next_token(JSON_TOKEN_NAME, "type");
+ json.put_next_token(JSON_TOKEN_STRING, "\"number\"");
+ json.put_next_token(JSON_TOKEN_OBJECT_END);
+ json.put_next_token(JSON_TOKEN_OBJECT_START);
+ json.put_next_token(JSON_TOKEN_NAME, "enum");
+ json.put_next_token(JSON_TOKEN_ARRAY_START);
+ json.put_next_token(JSON_TOKEN_STRING, "\"not_a_number\"");
+ json.put_next_token(JSON_TOKEN_STRING, "\"infinity\"");
+ json.put_next_token(JSON_TOKEN_STRING, "\"-infinity\"");
+ json.put_next_token(JSON_TOKEN_ARRAY_END);
+ json.put_next_token(JSON_TOKEN_OBJECT_END);
+ json.put_next_token(JSON_TOKEN_ARRAY_END);
+ }
break;
case T_BSTR:
case T_BSTR_A:
json.put_next_token(JSON_TOKEN_STRING, "\"^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$\"");
break;
case T_VERDICT:
- // enumerate the possible values
- json.put_next_token(JSON_TOKEN_NAME, "enum");
- json.put_next_token(JSON_TOKEN_ARRAY_START);
- json.put_next_token(JSON_TOKEN_STRING, "\"none\"");
- json.put_next_token(JSON_TOKEN_STRING, "\"pass\"");
- json.put_next_token(JSON_TOKEN_STRING, "\"inconc\"");
- json.put_next_token(JSON_TOKEN_STRING, "\"fail\"");
- json.put_next_token(JSON_TOKEN_STRING, "\"error\"");
- json.put_next_token(JSON_TOKEN_ARRAY_END);
+ if (has_restrictions) {
+ // the restrictions would only add another JSON enum (after the one
+ /// generated below), instead just insert the one with the restrictions
+ sub_type->generate_json_schema(json);
+ has_restrictions = false; // so they aren't generated twice
+ }
+ else {
+ // enumerate the possible values
+ json.put_next_token(JSON_TOKEN_NAME, "enum");
+ json.put_next_token(JSON_TOKEN_ARRAY_START);
+ json.put_next_token(JSON_TOKEN_STRING, "\"none\"");
+ json.put_next_token(JSON_TOKEN_STRING, "\"pass\"");
+ json.put_next_token(JSON_TOKEN_STRING, "\"inconc\"");
+ json.put_next_token(JSON_TOKEN_STRING, "\"fail\"");
+ json.put_next_token(JSON_TOKEN_STRING, "\"error\"");
+ json.put_next_token(JSON_TOKEN_ARRAY_END);
+ }
break;
case T_ENUM_T:
case T_ENUM_A:
default:
FATAL_ERROR("Type::generate_json_schema");
}
+
+ if (has_restrictions) {
+ // pass the tokenizer to the subtype to insert the type restrictions' schema
+ sub_type->generate_json_schema(json);
+ }
}
// insert default value (if any)
FATAL_ERROR("Type::generate_json_schema");
}
}
+
+ // insert schema extensions (if any)
+ if (jsonattrib != NULL) {
+ for (size_t i = 0; i < jsonattrib->schema_extensions.size(); ++i) {
+ json.put_next_token(JSON_TOKEN_NAME, jsonattrib->schema_extensions[i]->key);
+ char* value_str = mprintf("\"%s\"", jsonattrib->schema_extensions[i]->value);
+ json.put_next_token(JSON_TOKEN_STRING, value_str);
+ Free(value_str);
+ }
+ }
// end of type's schema
json.put_next_token(JSON_TOKEN_OBJECT_END);
"\"record of\"" : "\"set of\"");
} else {
// set the number of elements for arrays
- char* size_str = mprintf("%lu", get_nof_comps());
+ char* size_str = mprintf("%lu", (unsigned long)(get_nof_comps()));
json.put_next_token(JSON_TOKEN_NAME, "minItems");
json.put_next_token(JSON_TOKEN_NUMBER, size_str);
json.put_next_token(JSON_TOKEN_NAME, "maxItems");