clang warning elimination2
[deliverable/titan.core.git] / compiler2 / Type_codegen.cc
index cea911281e8eb7c7fa0ebaa2155d362ea2f12b7a..f6225b8938ae4008a5f3a280742d673a8607ded2 100644 (file)
@@ -1,10 +1,20 @@
-///////////////////////////////////////////////////////////////////////////////
-// 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"
@@ -243,6 +253,7 @@ void Type::generate_code_typedescriptor(output_struct *target)
     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:
@@ -362,15 +373,35 @@ void Type::generate_code_typedescriptor(output_struct *target)
       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"
@@ -389,24 +420,14 @@ void Type::generate_code_typedescriptor(output_struct *target)
         "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)
 }
 
@@ -479,9 +500,10 @@ void Type::generate_code_xerdescriptor(output_struct* target)
   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_);
 
@@ -495,6 +517,7 @@ void Type::generate_code_xerdescriptor(output_struct* target)
     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)
@@ -571,6 +594,12 @@ void Type::generate_code_xerdescriptor(output_struct* target)
   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) {
@@ -589,8 +618,8 @@ void Type::generate_code_xerdescriptor(output_struct* target)
   // 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
@@ -598,6 +627,7 @@ void Type::generate_code_xerdescriptor(output_struct* target)
     (any_elem ? " |ANY_ELEMENT" : ""),
     (atrib    ? " |XER_ATTRIBUTE" : ""),
     (base64   ? " |BASE_64" : ""),
+    (blocked  ? " |BLOCKED" : ""),
     (decimal  ? " |XER_DECIMAL" : ""),
     (embed    ? " |EMBED_VALUES" : ""),
     (list     ? " |XER_LIST" : ""),
@@ -612,15 +642,18 @@ void Type::generate_code_xerdescriptor(output_struct* target)
     (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)
@@ -630,7 +663,12 @@ 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,");
@@ -947,19 +985,20 @@ void Type::generate_code_jsondescriptor(output_struct *target)
   
   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);
   }
@@ -1078,6 +1117,25 @@ void Type::generate_code_Choice(output_struct *target)
   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));
@@ -1104,30 +1162,56 @@ void Type::generate_code_Choice(output_struct *target)
       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:
@@ -1470,6 +1554,7 @@ void Type::generate_code_Se(output_struct *target)
     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;
@@ -1510,6 +1595,7 @@ void Type::generate_code_Se(output_struct *target)
       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
 
@@ -1809,6 +1895,43 @@ bool Type::is_untagged() const { return xerattrib && xerattrib->untagged_; }
 
 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));
@@ -1825,10 +1948,8 @@ void Type::generate_code_SeOf(output_struct *target)
   }
   // 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 =
@@ -1894,7 +2015,7 @@ void Type::generate_code_SeOf(output_struct *target)
     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);
@@ -1970,7 +2091,8 @@ void Type::generate_code_Fat(output_struct *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(),"");
@@ -2118,7 +2240,7 @@ void Type::generate_code_done(output_struct *target)
      "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"
@@ -2126,7 +2248,7 @@ void Type::generate_code_done(output_struct *target)
      "} 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,
@@ -2298,8 +2420,9 @@ void Type::generate_code_ispresentbound(expression_struct *expr,
             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);
 
@@ -2355,8 +2478,9 @@ void Type::generate_code_ispresentbound(expression_struct *expr,
           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);
       }
@@ -2442,9 +2566,10 @@ void Type::generate_code_ispresentbound(expression_struct *expr,
 
       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,
@@ -2461,8 +2586,9 @@ void Type::generate_code_ispresentbound(expression_struct *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);
@@ -2617,10 +2743,10 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val
   // 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);
     }
@@ -2639,16 +2765,52 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val
   // 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) {
@@ -2664,33 +2826,48 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val
       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:
@@ -2720,28 +2897,59 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val
       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:
@@ -2757,11 +2965,17 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val
     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)
@@ -2795,6 +3009,16 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val
       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);
@@ -2813,7 +3037,7 @@ void Type::generate_json_schema_array(JSON_Tokenizer& json)
       "\"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");
@@ -2850,17 +3074,20 @@ void Type::generate_json_schema_record(JSON_Tokenizer& json)
     // 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;
     }
@@ -2870,7 +3097,8 @@ void Type::generate_json_schema_record(JSON_Tokenizer& json)
     
     // 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) ?
@@ -2895,7 +3123,7 @@ void Type::generate_json_schema_record(JSON_Tokenizer& json)
       // 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);
     }
@@ -2912,7 +3140,7 @@ void Type::generate_json_schema_record(JSON_Tokenizer& json)
         // 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);
       }
@@ -2947,7 +3175,7 @@ void Type::generate_json_schema_union(JSON_Tokenizer& json)
       // 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);
@@ -2965,7 +3193,7 @@ void Type::generate_json_schema_union(JSON_Tokenizer& json)
       // 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);
       
@@ -2979,6 +3207,23 @@ void Type::generate_json_schema_union(JSON_Tokenizer& json)
   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
This page took 0.032302 seconds and 5 git commands to generate.