-///////////////////////////////////////////////////////////////////////////////
-// 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"
case OT_TYPE_DEF:
case OT_COMP_FIELD:
case OT_RECORD_OF:
+ case OT_REF_SPEC:
force_xer = has_encoding(CT_XER); // && (is_ref() || (xerattrib && !xerattrib->empty()));
break;
default:
case T_UNIVERSALSTRING:
case T_BMPSTRING:
case T_VERDICT:
+ case T_NULL:
+ case T_OID:
+ case T_ROID:
+ case T_ANY:
// use predefined JSON descriptors instead of null pointers for basic types
target->source.global_vars = mputprintf(target->source.global_vars,
"&%s_json_, ", gennamejsondescriptor.c_str());
break;
+ case T_ENUM_T:
+ case T_ENUM_A:
+ // use a predefined JSON descriptor for enumerated types
+ target->source.global_vars = mputstr(target->source.global_vars,
+ "&ENUMERATED_json_, ");
+ break;
default:
target->source.global_vars = mputstr(target->source.global_vars,
"NULL, ");
}
}
+
+ if (T_SEQOF == get_type_refd_last()->typetype ||
+ T_SETOF == get_type_refd_last()->typetype) {
+ target->source.global_vars=mputprintf(target->source.global_vars,
+ "&%s_descr_, ", get_type_refd_last()->u.seof.ofType->get_genname_typedescriptor(my_scope).c_str());
+ }
+ else {
+ target->source.global_vars = mputstr(target->source.global_vars,
+ "NULL, ");
+ }
target->source.global_vars=mputprintf(target->source.global_vars,
"TTCN_Typedescriptor_t::%s };\n"
"const TTCN_Typedescriptor_t& %s_descr_ = %s_descr_;\n",
gennameown_str, gennametypedescriptor.c_str());
}
- else {
- /* In general, we avoid generating a XER descriptor for
- * "artificial" types. */
-
- if (ownertype==OT_REF_SPEC) {
- // A XER descriptor without a TTCN descriptor to own it
- generate_code_xerdescriptor(target);
- }
#ifndef NDEBUG
- else
- target->source.global_vars = mputprintf(target->source.global_vars,
- "// %s_xer_ elided\n", gennameown_str);
-
+ else {
target->source.global_vars = mputprintf( target->source.global_vars,
"// %s_descr_ not needed, use %s_descr_\n",
gennameown_str, gennametypedescriptor.c_str());
-#endif
} // if(needs_alias())
+#endif
+
} // if (gennameown == gennametypedescriptor)
}
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;
if (xerattrib) {
change_name(last_s, xerattrib->name_);
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)
size_t last_len = 2 + last_s.size(); // 2 for > \n
size_t bxer_len = 2 + bxer_name.size(); // 2 for > \n
+ if ((T_SEQOF == last->typetype || T_SETOF == last->typetype) &&
+ T_ANYTYPE != last->u.seof.ofType->get_type_refd_last()->typetype) {
+ // anytypes don't have XER descriptors
+ oftype_descr_name = mprintf("&%s_xer_", last->u.seof.ofType->get_genname_typedescriptor(my_scope).c_str());
+ }
+
// Generate a separate variable for the namespace URIs, if there are any
char* ns_uris_var = 0;
if (ns_uris && nof_ns_uris) {
// 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, "
- "&%s, %ld, %u, %s };\n",
+ " {%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
(unsigned long)bxer_len, (unsigned long)last_len, // lengths
(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",
ns_index,
nof_ns_uris,
- (ns_uris_var ? ns_uris_var : "NULL")
+ (ns_uris_var ? ns_uris_var : "NULL"),
+ (oftype_descr_name ? oftype_descr_name : "NULL")
);
Free(ns_uris_var);
+ Free(oftype_descr_name);
}
void Type::generate_code_rawdescriptor(output_struct *target)
"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.dispname = id.get_ttcnname().c_str();
cur.isOptional = cf->get_is_optional();
cur.isDefault = cf->has_default();
+ cur.optimizedMemAlloc = cur.of_type && (type->get_optimize_attribute() == "memalloc");
if (cur.isDefault) {
Value *defval = cf->get_defval();
const_def cdef;
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
void Type::generate_code_SeOf(output_struct *target)
{
+ const Type *oftypelast = u.seof.ofType->get_type_refd_last();
+ const string& oftypename = u.seof.ofType->get_genname_value(my_scope);
+ boolean optimized_memalloc = !use_runtime_2 && get_optimize_attribute() == "memalloc";
+
+ if (is_pregenerated()) {
+ switch(oftypelast->typetype) {
+ case T_USTR:
+ case T_UTF8STRING:
+ case T_TELETEXSTRING:
+ case T_VIDEOTEXSTRING:
+ case T_GRAPHICSTRING:
+ case T_GENERALSTRING:
+ case T_UNIVERSALSTRING:
+ case T_BMPSTRING:
+ case T_OBJECTDESCRIPTOR:
+ 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(),
+ (typetype == T_SEQOF) ? "RECORD" : "SET",
+ optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str());
+ return;
+ default:
+ // 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(),
+ optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str(),
+ (typetype == T_SEQOF) ? "RECORD" : "SET", oftypename.c_str(),
+ optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str());
+ return;
+ }
+ }
+
stringpool pool;
struct_of_def sofdef;
memset(&sofdef, 0, sizeof(sofdef));
}
// If a record of UTF8String, we need to prepare for ANY-ATTRIBUTES and
// ANY-ELEMENT
- const Type *oftypelast = u.seof.ofType->get_type_refd_last();
sofdef.xerAnyAttrElem = oftypelast->typetype == T_USTR
|| oftypelast->typetype == T_UTF8STRING;
- const string& oftypename = u.seof.ofType->get_genname_value(my_scope);
sofdef.type = oftypename.c_str();
sofdef.has_opentypes = get_has_opentypes();
const string& oftypedescrname =
sofdef.hasRaw=true;
} else sofdef.hasRaw=false;
- if (!use_runtime_2 && get_optimize_attribute()=="memalloc") {
+ if (optimized_memalloc) {
defRecordOfClassMemAllocOptimized(&sofdef, target);
} else {
defRecordOfClass(&sofdef, target);
}
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);
// stored if this is a field of a union with the "as value" coding instruction
if (ownertype == OT_COMP_FIELD) {
CompField* cf = static_cast<CompField*>(owner);
- if(as_value || (cf->get_type()->jsonattrib != NULL
- && cf->get_type()->jsonattrib->alias != NULL)) {
+ if (as_value || (cf->get_type()->jsonattrib != NULL
+ && cf->get_type()->jsonattrib->alias != NULL)) {
json.put_next_token(JSON_TOKEN_NAME, "originalName");
- char* field_str = mprintf("\"%s\"", cf->get_name().get_dispname().c_str());
+ char* field_str = mprintf("\"%s\"", cf->get_name().get_ttcnname().c_str());
json.put_next_token(JSON_TOKEN_STRING, field_str);
Free(field_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
- if (embedded && (last->ownertype == OT_TYPE_DEF /* TTCN-3 type definition */
- || last->ownertype == OT_TYPE_ASS /* ASN.1 type assignment */ )) {
+ // 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 (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_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:
case T_HSTR:
case T_OSTR:
+ case T_ANY:
// use the JSON string type and add a pattern to only allow bits or hex digits
json.put_next_token(JSON_TOKEN_NAME, "type");
json.put_next_token(JSON_TOKEN_STRING, "\"string\"");
+ json.put_next_token(JSON_TOKEN_NAME, "subType");
+ json.put_next_token(JSON_TOKEN_STRING,
+ (last->typetype == T_OSTR || last->typetype == T_ANY) ? "\"octetstring\"" :
+ ((last->typetype == T_HSTR) ? "\"hexstring\"" : "\"bitstring\""));
json.put_next_token(JSON_TOKEN_NAME, "pattern");
json.put_next_token(JSON_TOKEN_STRING,
- (last->typetype == T_OSTR) ? "\"^([0-9A-Fa-f][0-9A-Fa-f])*$\"" :
+ (last->typetype == T_OSTR || last->typetype == T_ANY) ? "\"^([0-9A-Fa-f][0-9A-Fa-f])*$\"" :
((last->typetype == T_HSTR) ? "\"^[0-9A-Fa-f]*$\"" : "\"^[01]*$\""));
break;
case T_CSTR:
json.put_next_token(JSON_TOKEN_NAME, "subType");
json.put_next_token(JSON_TOKEN_STRING, "\"universal charstring\"");
break;
+ case T_OID:
+ case T_ROID:
+ json.put_next_token(JSON_TOKEN_NAME, "type");
+ json.put_next_token(JSON_TOKEN_STRING, "\"string\"");
+ json.put_next_token(JSON_TOKEN_NAME, "subType");
+ json.put_next_token(JSON_TOKEN_STRING, "\"objid\"");
+ json.put_next_token(JSON_TOKEN_NAME, "pattern");
+ 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:
// enumerate the possible values
json.put_next_token(JSON_TOKEN_NAME, "enum");
json.put_next_token(JSON_TOKEN_ARRAY_START);
- for (size_t i = 0; i < u.enums.eis->get_nof_eis(); ++i) {
- char* enum_str = mprintf("\"%s\"", get_ei_byIndex(i)->get_name().get_dispname().c_str());
+ for (size_t i = 0; i < last->u.enums.eis->get_nof_eis(); ++i) {
+ char* enum_str = mprintf("\"%s\"", last->get_ei_byIndex(i)->get_name().get_ttcnname().c_str());
json.put_next_token(JSON_TOKEN_STRING, enum_str);
Free(enum_str);
}
json.put_next_token(JSON_TOKEN_ARRAY_END);
+ // list the numeric values for the enumerated items
+ json.put_next_token(JSON_TOKEN_NAME, "numericValues");
+ json.put_next_token(JSON_TOKEN_ARRAY_START);
+ for (size_t i = 0; i < last->u.enums.eis->get_nof_eis(); ++i) {
+ char* num_val_str = mprintf("%lli", last->get_ei_byIndex(i)->get_value()->get_val_Int()->get_val());
+ json.put_next_token(JSON_TOKEN_NUMBER, num_val_str);
+ Free(num_val_str);
+ }
+ json.put_next_token(JSON_TOKEN_ARRAY_END);
+ break;
+ case T_NULL:
+ // use the JSON null value for the ASN.1 NULL type
+ json.put_next_token(JSON_TOKEN_NAME, "type");
+ json.put_next_token(JSON_TOKEN_STRING, "\"null\"");
break;
case T_SEQOF:
case T_SETOF:
case T_CHOICE_T:
case T_CHOICE_A:
case T_ANYTYPE:
+ case T_OPENTYPE:
last->generate_json_schema_union(json);
break;
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");
// use the field's alias if it has one
json.put_next_token(JSON_TOKEN_NAME,
(field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
- field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str());
+ field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
// optional fields can also get the JSON null value
if (get_comp_byIndex(i)->get_is_optional()) {
- json.put_next_token(JSON_TOKEN_OBJECT_START);
- 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, "\"null\"");
- json.put_next_token(JSON_TOKEN_OBJECT_END);
+ // special case: ASN NULL type, since it uses the JSON literal "null" as a value
+ if (T_NULL != field->get_type_refd_last()->typetype) {
+ json.put_next_token(JSON_TOKEN_OBJECT_START);
+ 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, "\"null\"");
+ json.put_next_token(JSON_TOKEN_OBJECT_END);
+ }
} else if (!has_non_optional) {
has_non_optional = true;
}
// for optional fields: specify the presence of the "omit as null" coding instruction
// and close structures
- if (get_comp_byIndex(i)->get_is_optional()) {
+ if (get_comp_byIndex(i)->get_is_optional() &&
+ T_NULL != field->get_type_refd_last()->typetype) {
json.put_next_token(JSON_TOKEN_ARRAY_END);
json.put_next_token(JSON_TOKEN_NAME, "omitAsNull");
json.put_next_token((field->jsonattrib != NULL && field->jsonattrib->omit_as_null) ?
// use the field's alias if it has one
char* field_str = mprintf("\"%s\"",
(field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
- field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str());
+ field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
json.put_next_token(JSON_TOKEN_STRING, field_str);
Free(field_str);
}
// use the field's alias if it has one
char* field_str = mprintf("\"%s\"",
(field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
- field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str());
+ field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
json.put_next_token(JSON_TOKEN_STRING, field_str);
Free(field_str);
}
// use the alternative's alias if it has one
json.put_next_token(JSON_TOKEN_NAME,
(field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
- field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str());
+ field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
// let the alternative's type insert its schema
field->generate_json_schema(json, true, false);
// use the alternative's alias here as well
char* field_str = mprintf("\"%s\"",
(field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
- field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str());
+ field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
json.put_next_token(JSON_TOKEN_STRING, field_str);
Free(field_str);
json.put_next_token(JSON_TOKEN_ARRAY_END);
}
+void Type::generate_json_schema_ref(JSON_Tokenizer& json)
+{
+ // start the object containing the reference
+ json.put_next_token(JSON_TOKEN_OBJECT_START);
+
+ // insert the reference
+ json.put_next_token(JSON_TOKEN_NAME, "$ref");
+ char* ref_str = mprintf("\"#/definitions/%s/%s\"",
+ my_scope->get_scope_mod()->get_modid().get_ttcnname().c_str(),
+ get_dispname().c_str());
+ json.put_next_token(JSON_TOKEN_STRING, ref_str);
+ Free(ref_str);
+
+ // the object will be closed later, as it may contain other properties
+}
+
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
} // namespace Common