warning elimination reported by clang
[deliverable/titan.core.git] / core2 / Basetype2.cc
index 2bffe70a5d5cbbd86d2e6ee6909257c5bf1e42b2..1ddac029f5783313b5f287a4906a5fc9638c986f 100644 (file)
@@ -1,10 +1,23 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2000-2015 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
+ *   Delic, Adam
+ *   Kovacs, Ferenc
+ *   Raduly, Csaba
+ *   Szabados, Kristof
+ *   Szabo, Bence Janos
+ *   Pandi, Krisztian
+ *
+ ******************************************************************************/
 #include "Basetype.hh"
 #include "TEXT.hh"
 #include "BER.hh"
@@ -21,6 +34,7 @@
 #include "Charstring.hh"
 #include "Universal_charstring.hh"
 #include "Addfunc.hh"
+#include "PreGenRecordOf.hh"
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -175,6 +189,13 @@ int Base_Type::RAW_encode_negtest_raw(RAW_enc_tree&) const
   return 0;
 }
 
+int Base_Type::JSON_encode_negtest_raw(JSON_Tokenizer&) const
+{
+  TTCN_error("A value of type %s cannot be used as erroneous raw value for JSON encoding.",
+             get_descriptor()->name);
+  return 0;
+}
+
 int Base_Type::XER_encode_negtest(const Erroneous_descriptor_t* /*p_err_descr*/,
   const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
 {
@@ -188,6 +209,13 @@ int Base_Type::RAW_encode_negtest(const Erroneous_descriptor_t *,
   return 0;
 }
 
+int Base_Type::JSON_encode_negtest(const Erroneous_descriptor_t* /*p_err_descr*/,
+  const TTCN_Typedescriptor_t& /*p_td*/, JSON_Tokenizer& /*p_tok*/) const
+{
+  TTCN_error("Internal error: calling Base_Type::JSON_encode_negtest().");
+  return 0;
+}
+
 #else
 #error this is for RT2 only
 #endif
@@ -1421,6 +1449,41 @@ int Record_Of_Type::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr
 }
 
 int Record_Of_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
+{
+  if (err_descr) {
+         return JSON_encode_negtest(err_descr, p_td, p_tok);
+  }
+  
+  if (!is_bound()) {
+    TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
+      "Encoding an unbound %s of value.", is_set() ? "set" : "record");
+    return -1;
+  }
+  
+  int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
+  
+  for (int i = 0; i < get_nof_elements(); ++i) {
+    if (NULL != p_td.json && p_td.json->metainfo_unbound && !get_at(i)->is_bound()) {
+      // unbound elements are encoded as { "metainfo []" : "unbound" }
+      enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, "metainfo []");
+      enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
+      enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+    }
+    else {
+      int ret_val = get_at(i)->JSON_encode(*p_td.oftype_descr, p_tok);
+      if (0 > ret_val) break;
+      enc_len += ret_val;
+    }
+  }
+  
+  enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
+  return enc_len;
+}
+
+int Record_Of_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
+                                        const TTCN_Typedescriptor_t& p_td,
+                                        JSON_Tokenizer& p_tok) const 
 {
   if (!is_bound()) {
     TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
@@ -1430,10 +1493,78 @@ int Record_Of_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenize
   
   int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
   
-  for(int i = 0; i < get_nof_elements(); ++i) {
-    int ret_val = get_at(i)->JSON_encode(*p_td.oftype_descr, p_tok);
-    if (0 > ret_val) break;
-    enc_len += ret_val;
+  int values_idx = 0;
+  int edescr_idx = 0;
+  
+  for (int i = 0; i < get_nof_elements(); ++i) {
+    if (-1 != p_err_descr->omit_before && p_err_descr->omit_before > i) {
+      continue;
+    }
+    
+    const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(i, values_idx);
+    const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(i, edescr_idx);
+    
+    if (NULL != err_vals && NULL != err_vals->before) {
+      if (NULL == err_vals->before->errval) {
+        TTCN_error("internal error: erroneous before value missing");
+      }
+      if (err_vals->before->raw) {
+        enc_len += err_vals->before->errval->JSON_encode_negtest_raw(p_tok);
+      } else {
+        if (NULL == err_vals->before->type_descr) {
+          TTCN_error("internal error: erroneous before typedescriptor missing");
+        }
+        enc_len += err_vals->before->errval->JSON_encode(*(err_vals->before->type_descr), p_tok);
+      }
+    }
+    
+    if (NULL != err_vals && NULL != err_vals->value) {
+      if (NULL != err_vals->value->errval) {
+        if (err_vals->value->raw) {
+          enc_len += err_vals->value->errval->JSON_encode_negtest_raw(p_tok);
+        } else {
+          if (NULL == err_vals->value->type_descr) {
+            TTCN_error("internal error: erroneous before typedescriptor missing");
+          }
+          enc_len += err_vals->value->errval->JSON_encode(*(err_vals->value->type_descr), p_tok);
+        }
+      }
+    }
+    else if (NULL != p_td.json && p_td.json->metainfo_unbound && !get_at(i)->is_bound()) {
+      // unbound elements are encoded as { "metainfo []" : "unbound" }
+      enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, "metainfo []");
+      enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
+      enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+    }
+    else {
+      int ret_val;
+      if (NULL != emb_descr) {
+        ret_val = get_at(i)->JSON_encode_negtest(emb_descr, *p_td.oftype_descr, p_tok);
+      } else {
+        ret_val = get_at(i)->JSON_encode(*p_td.oftype_descr, p_tok);
+      }
+      if (0 > ret_val) break;
+      enc_len += ret_val;
+    }
+    
+    if (NULL != err_vals && NULL != err_vals->after) {
+      if (NULL == err_vals->after->errval) {
+        TTCN_error("internal error: erroneous after value missing");
+      }
+      if (err_vals->after->raw) {
+        enc_len += err_vals->after->errval->JSON_encode_negtest_raw(p_tok);
+      } else {
+        if (NULL == err_vals->after->type_descr) {
+          TTCN_error("internal error: erroneous before typedescriptor missing");
+        }
+        enc_len += err_vals->after->errval->JSON_encode(*(err_vals->after->type_descr), p_tok);
+      }
+    }
+    
+    if (-1 != p_err_descr->omit_after && p_err_descr->omit_after <= i) {
+      break;
+    }
   }
   
   enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
@@ -1453,11 +1584,35 @@ int Record_Of_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenize
   } 
   
   set_size(0);
-  while (true) {
+  for (int nof_elements = 0; true; ++nof_elements) {
     // Read value tokens until we reach some other token
     size_t buf_pos = p_tok.get_buf_pos();
+    int ret_val;
+    if (NULL != p_td.json && p_td.json->metainfo_unbound) {
+      // check for metainfo object
+      ret_val = p_tok.get_next_token(&token, NULL, NULL);
+      if (JSON_TOKEN_OBJECT_START == token) {
+        char* value = NULL;
+        size_t value_len = 0;
+        ret_val += p_tok.get_next_token(&token, &value, &value_len);
+        if (JSON_TOKEN_NAME == token && 11 == value_len &&
+            0 == strncmp(value, "metainfo []", 11)) {
+          ret_val += p_tok.get_next_token(&token, &value, &value_len);
+          if (JSON_TOKEN_STRING == token && 9 == value_len &&
+              0 == strncmp(value, "\"unbound\"", 9)) {
+            ret_val = p_tok.get_next_token(&token, NULL, NULL);
+            if (JSON_TOKEN_OBJECT_END == token) {
+              dec_len += ret_val;
+              continue;
+            }
+          }
+        }
+      }
+      // metainfo object not found, jump back and let the element type decode it
+      p_tok.set_buf_pos(buf_pos);
+    }
     Base_Type* val = create_elem();
-    int ret_val = val->JSON_decode(*p_td.oftype_descr, p_tok, p_silent);
+    ret_val = val->JSON_decode(*p_td.oftype_descr, p_tok, p_silent);
     if (JSON_ERROR_INVALID_TOKEN == ret_val) {
       // undo the last action on the buffer
       p_tok.set_buf_pos(buf_pos);
@@ -1473,12 +1628,12 @@ int Record_Of_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenize
     }
     if (NULL == refd_ind_ptr) {
       val_ptr->value_elements = (Base_Type**)reallocate_pointers(
-        (void**)val_ptr->value_elements, val_ptr->n_elements, val_ptr->n_elements + 1);
-      val_ptr->value_elements[val_ptr->n_elements] = val;
-      val_ptr->n_elements++;
+        (void**)val_ptr->value_elements, val_ptr->n_elements, nof_elements + 1);
+      val_ptr->value_elements[nof_elements] = val;
+      val_ptr->n_elements = nof_elements + 1;
     }
     else {
-      get_at(get_nof_elements())->set_value(val);
+      get_at(nof_elements)->set_value(val);
       delete val;
     }
     dec_len += ret_val;
@@ -1600,7 +1755,7 @@ void Record_Of_Type::decode(const TTCN_Typedescriptor_t& p_td,
     for (int success=reader.Read(); success==1; success=reader.Read()) {
       if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break;
     }
-    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, 0);
+    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, XER_NONE, 0);
     size_t bytes = reader.ByteConsumed();
     p_buf.set_pos(bytes);
     break;}
@@ -2098,7 +2253,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
 }
 
 int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
-  XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t* emb_val)
+  XmlReaderWrap& reader, unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t* emb_val)
 {
   int exer = is_exer(flavor);
   int xerbits = p_td.xer_bits;
@@ -2177,7 +2332,7 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
       // The call to the non-const operator[], I mean get_at(), creates
       // a new element (because it is indexing one past the last element).
       // Then we call its XER_decode with the temporary XML reader.
-      get_at(get_nof_elements())->XER_decode(sub_xer, reader2, flavor, 0);
+      get_at(get_nof_elements())->XER_decode(sub_xer, reader2, flavor, flavor2, 0);
       if (flavor & EXIT_ON_ERROR && !is_elem_bound(get_nof_elements() - 1)) {
         if (1 == get_nof_elements()) {
           // Failed to decode even the first element
@@ -2243,10 +2398,10 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
             }
             ec_1.set_msg("%d: ", get_nof_elements());
             /* The call to the non-const get_at() creates the element */
-            get_at(get_nof_elements())->XER_decode(*p_td.oftype_descr, reader, flavor, emb_val);
-            if (0 != emb_val && !own_tag && get_nof_elements() > 1) {
-              ++emb_val->embval_index;
-            }
+            get_at(get_nof_elements())->XER_decode(*p_td.oftype_descr, reader, flavor, flavor2, emb_val);
+          }
+          if (0 != emb_val && !own_tag && get_nof_elements() > 1) {
+            ++emb_val->embval_index;
           }
         }
         else if (XML_READER_TYPE_END_ELEMENT == type) {
@@ -2433,7 +2588,6 @@ boolean operator!=(null_type null_value,
 
 boolean Record_Type::is_bound() const
 {
-  if (bound_flag) return TRUE;
   int field_cnt = get_count();
   for (int field_idx=0; field_idx<field_cnt; field_idx++) {
     const Base_Type* temp = get_at(field_idx);
@@ -2447,9 +2601,6 @@ boolean Record_Type::is_bound() const
 
 boolean Record_Type::is_value() const
 {
-  if (!is_bound()) {
-    return FALSE;
-  }
   int field_cnt = get_count();
   for (int field_idx=0; field_idx<field_cnt; field_idx++) {
     const Base_Type* temp = get_at(field_idx);
@@ -2469,7 +2620,6 @@ void Record_Type::clean_up()
   for (int field_idx=0; field_idx<field_cnt; field_idx++) {
     get_at(field_idx)->clean_up();
   }
-  bound_flag = FALSE;
 }
 
 void Record_Type::log() const
@@ -2491,7 +2641,6 @@ void Record_Type::log() const
 }
 
 void Record_Type::set_param(Module_Param& param) {
-  bound_flag = TRUE;
   if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
       param.get_id()->next_name()) {
     // Haven't reached the end of the module parameter name
@@ -2602,10 +2751,6 @@ void Record_Type::set_implicit_omit()
 
 int Record_Type::size_of() const
 {
-  if (!is_bound()) {
-    TTCN_error("Calculating the size of an unbound record/set value of type %s",
-      get_descriptor()->name);
-  }
   int opt_count = optional_count();
   if (opt_count==0) return get_count();
   const int* optional_indexes = get_optional_indexes();
@@ -2629,7 +2774,6 @@ void Record_Type::encode_text(Text_Buf& text_buf) const
 
 void Record_Type::decode_text(Text_Buf& text_buf)
 {
-  bound_flag = TRUE;
   int field_cnt = get_count();
   for (int field_idx=0; field_idx<field_cnt; field_idx++)
     get_at(field_idx)->decode_text(text_buf);
@@ -2638,9 +2782,6 @@ void Record_Type::decode_text(Text_Buf& text_buf)
 boolean Record_Type::is_equal(const Base_Type* other_value) const
 {
   const Record_Type* other_record = static_cast<const Record_Type*>(other_value);
-  if (!is_bound() && !other_record->is_bound()) {
-    return TRUE;
-  }
   int field_cnt = get_count();
   for (int field_idx=0; field_idx<field_cnt; field_idx++) {
     const Base_Type* elem = get_at(field_idx);
@@ -2672,7 +2813,6 @@ void Record_Type::set_value(const Base_Type* other_value)
     }
   }
   err_descr = other_record->err_descr;
-  bound_flag = TRUE;
 }
 
 void Record_Type::encode(const TTCN_Typedescriptor_t& p_td,
@@ -2795,7 +2935,7 @@ void Record_Type::decode(const TTCN_Typedescriptor_t& p_td,
     for (int success=reader.Read(); success==1; success=reader.Read()) {
       if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break;
     }
-    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, 0);
+    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, XER_NONE, 0);
     size_t bytes = reader.ByteConsumed();
     p_buf.set_pos(bytes);
     break;}
@@ -2953,7 +3093,6 @@ ASN_BER_TLV_t* Record_Type::BER_encode_TLV_negtest(const Erroneous_descriptor_t*
 boolean Record_Type::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
   const ASN_BER_TLV_t& p_tlv, unsigned L_form)
 {
-  bound_flag = TRUE;
   BER_chk_descr(p_td);
   ASN_BER_TLV_t stripped_tlv;
   BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);
@@ -3060,7 +3199,6 @@ boolean Record_Type::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
 
 void Record_Type::BER_decode_opentypes(TTCN_Type_list& p_typelist, unsigned L_form)
 {
-  bound_flag = TRUE;
   p_typelist.push(this);
   TTCN_EncDec_ErrorContext ec_0("Component '");
   TTCN_EncDec_ErrorContext ec_1;
@@ -3257,7 +3395,6 @@ int Record_Type::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr,
 int Record_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff,
   int limit, raw_order_t top_bit_ord, boolean no_err, int, boolean)
 {
-  bound_flag = TRUE;
   int field_cnt = get_count();
   int opt_cnt = optional_count();
   int mand_num = field_cnt - opt_cnt; // expected mandatory fields
@@ -3531,7 +3668,6 @@ int Record_Type::TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
 int Record_Type::TEXT_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff,
   Limit_Token_List& limit, boolean no_err, boolean /*first_call*/)
 {
-  bound_flag = TRUE;
   if (is_set()) {
     int decoded_length=0;
     int decoded_field_length=0;
@@ -3996,8 +4132,16 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
   // start tag, i.e. the ">\n". This is used later to "back up" over it.
   int start_tag_len = 1 + indenting;
   // The EMBED-VALUES member, if applicable
-  const Record_Of_Type* const embed_values = (p_td.xer_bits & EMBED_VALUES)
-  ? static_cast<const Record_Of_Type*>(get_at(0)) : 0;
+  const Record_Of_Type* embed_values = 0;
+  if (p_td.xer_bits & EMBED_VALUES) {
+    embed_values = dynamic_cast<const Record_Of_Type*>(get_at(0));
+    if (NULL == embed_values) {
+      const OPTIONAL<Record_Of_Type>* const embed_opt = static_cast<const OPTIONAL<Record_Of_Type>*>(get_at(0));
+      if(embed_opt->is_present()) {
+        embed_values = &(*embed_opt)();
+      }
+    }
+  }
   // The USE-ORDER member, if applicable
   const Record_Of_Type* const use_order = (p_td.xer_bits & USE_ORDER)
   ? static_cast<const Record_Of_Type*>(get_at(uo_index)) : 0;
@@ -4057,7 +4201,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
       - (!indenting || delay_close || (exer && (p_td.xer_bits & HAS_1UNTAGGED))),
       (cbyte*)p_td.names[exer]);
   }
-  else if (flavor & USE_TYPE_ATTR) {
+  else if (flavor & (USE_NIL|USE_TYPE_ATTR)) {
     // reopen the parent's start tag by overwriting the '>'
     size_t buf_len = p_buf.get_len();
     const unsigned char * const buf_data = p_buf.get_data();
@@ -4094,7 +4238,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
     if (p_td.xer_bits & XER_ATTRIBUTE) p_buf.put_c('\'');
   }
   else { // not USE-QNAME
-    if (!exer && (p_td.xer_bits & EMBED_VALUES)) {
+    if (!exer && (p_td.xer_bits & EMBED_VALUES) && embed_values != NULL) {
       // The EMBED-VALUES member as an ordinary record of string
       sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1, 0);
     }
@@ -4162,7 +4306,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
 
     if (exer && (p_td.xer_bits & EMBED_VALUES)) {
       /* write the first string */
-      if (embed_values->size_of() > 0) {
+      if (embed_values != NULL && embed_values->size_of() > 0) {
         sub_len += embed_values->get_at(0)->XER_encode(UNIVERSAL_CHARSTRING_xer_,
           p_buf, flavor | EMBED_VALUES, indent+1, 0);
       }
@@ -4190,9 +4334,8 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
         ++n_optionals;
       }
 
-      int expected_min = field_cnt - first_nonattr - n_optionals;
       int expected_max = field_cnt - first_nonattr;
-
+      int expected_min = expected_max - n_optionals;
 
       if ((p_td.xer_bits & USE_NIL) && get_at(field_cnt-1)->ispresent()) {
         // The special case when USE_ORDER refers to the fields of a field,
@@ -4246,7 +4389,8 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
     // early_to_bed can only be true if exer is true (transitive through nil_attribute)
     if (!early_to_bed) {
       embed_values_enc_struct_t* emb_val = 0;
-      if (exer && (p_td.xer_bits & EMBED_VALUES) && embed_values->size_of() > 1) {
+      if (exer && (p_td.xer_bits & EMBED_VALUES) && 
+          embed_values != NULL && embed_values->size_of() > 1) {
         emb_val = new embed_values_enc_struct_t;
         emb_val->embval_array = embed_values;
         emb_val->embval_index = 1;
@@ -4276,7 +4420,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
 
         // Now the next embed-values string (NOT affected by USE-ORDER!)
         if (exer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&
-            emb_val->embval_index < embed_values->size_of()) {
+            embed_values != NULL && emb_val->embval_index < embed_values->size_of()) {
           embed_values->get_at(emb_val->embval_index)->XER_encode(UNIVERSAL_CHARSTRING_xer_
             , p_buf, flavor | EMBED_VALUES, indent+1, 0);
           ++emb_val->embval_index;
@@ -4284,7 +4428,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
       } //for
       
       if (0 != emb_val) {
-        if (emb_val->embval_index < embed_values->size_of()) {
+        if (embed_values != NULL && emb_val->embval_index < embed_values->size_of()) {
           ec_1.set_msg("%s': ", fld_name(0));
           TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,
             "Too many EMBED-VALUEs specified: %d (expected %d or less)",
@@ -4973,9 +5117,8 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
 }
 
 int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
-                            unsigned int flavor, embed_values_dec_struct_t*)
+                            unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t*)
 {
-  bound_flag = TRUE;
   int exer = is_exer(flavor);
   int success, type;
   int depth=-1; // depth of the start tag
@@ -4987,10 +5130,11 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
   boolean tag_closed = (flavor & PARENT_CLOSED) != 0;
   // If the parent has USE-TYPE, our ATTRIBUTE members can be found
   // in the parent's tag (the reader is sitting on it).
-  const boolean parent_tag = exer && (flavor & (/*USE_NIL|*/ USE_TYPE_ATTR));
+  const boolean parent_tag = exer && ((flavor & USE_TYPE_ATTR) || (flavor2 & USE_NIL_PARENT_TAG));
 
   // Filter out flags passed by our parent. These are not for the fields.
   flavor &= XER_MASK; // also removes XER_TOPLEVEL
+  flavor2 = XER_NONE; // Remove only bit: USE_NIL_PARENT_TAG (for now)
 
   const int field_cnt = get_count();
   const int num_attributes = get_xer_num_attr();
@@ -5003,7 +5147,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
   // fields); normal processing start at this field.
   const int start_at = uo_index + ((p_td.xer_bits & USE_ORDER) != 0);
   const int first_nonattr = start_at + num_attributes;
-
+  
   // The index of the ANY-ATTRIBUTES member, if any
   int aa_index = -1;
   for (int k = 0; k < first_nonattr; ++k) {
@@ -5071,12 +5215,15 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
     TTCN_EncDec_ErrorContext ec_0("Component '");
     TTCN_EncDec_ErrorContext ec_1;
     boolean usenil_attribute = FALSE; // true if found and said yes
+    // If nillable and the nillable field is a record type, that has attributes
+    // then it will become true, and skips the processing of the fields after
+    boolean already_processed = FALSE;
     if (!exer) {
       if (!reader.IsEmptyElement()) reader.Read();
       // First, the (would-be) attributes (unaffected by USE-ORDER)
       for (i = 0; i < first_nonattr; i++) {
         ec_1.set_msg("%s': ", fld_name(i));
-        get_at(i)->XER_decode(*xer_descr(i), reader, flavor, 0);
+        get_at(i)->XER_decode(*xer_descr(i), reader, flavor, flavor2, 0);
       } // next field
     }
     else if (own_tag || parent_tag) { // EXER and not UNTAGGED: do attributes
@@ -5104,7 +5251,12 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
       }
 
       /* * * * * * * * * Attributes * * * * * * * * * * * * * */
-      for (success = reader.MoveToFirstAttribute();
+      if(parent_tag && reader.NodeType() == XML_READER_TYPE_ATTRIBUTE) {
+        success = reader.Ok();
+      } else {
+        success = reader.MoveToFirstAttribute();
+      }
+      for (;
         success == 1 && reader.NodeType() == XML_READER_TYPE_ATTRIBUTE;
         success = reader.AdvanceAttribute())
       {
@@ -5118,7 +5270,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
         if (field_index != -1) {
           // There is a field. Let it decode the attribute.
           ec_1.set_msg("%s': ", fld_name(field_index));
-          get_at(field_index)->XER_decode(*xer_descr(field_index), reader, flavor, 0);
+          get_at(field_index)->XER_decode(*xer_descr(field_index), reader, flavor, flavor2, 0);
           continue;
         }
 
@@ -5140,8 +5292,13 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
 
             continue;
           } // it is the "nil" attribute
+          // else, let the nillable field decode the next attributes, it is possible
+          // that it belongs to him
+          get_at(field_cnt-1)->XER_decode(*xer_descr(field_cnt-1), reader, flavor | USE_NIL, flavor2 | USE_NIL_PARENT_TAG, 0);
+          already_processed = TRUE;
+          break;
         } // type has USE-NIL
-
+        
         if (parent_tag) {
           const char *prefix = (const char*)reader.Prefix();
           // prefix may be NULL, control_ns->px is never NULL or empty
@@ -5202,7 +5359,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
             continue;
           }
         }
-
+        
         // Nobody wanted the attribute. That is an error.
         ec_0.set_msg(" "); ec_1.set_msg(" ");
         TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
@@ -5221,15 +5378,23 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
       }
 
       i = first_nonattr; // finished with attributes
-      // AdvanceAttribute did MoveToElement. Move into the content (if any).
-      if (!reader.IsEmptyElement()) reader.Read();
+      // AdvanceAttribute did MoveToElement. Move into the content (if any),
+      // except when the reader is already moved in(already_processed).
+      if (!reader.IsEmptyElement() && !already_processed) reader.Read();
     } // end if (own_tag)
-
+    
     /* * * * * * * * Non-attributes (elements) * * * * * * * * * * * */
     embed_values_dec_struct_t* emb_val = 0;
+    bool emb_val_optional = false;
     if (exer && (p_td.xer_bits & EMBED_VALUES)) {
       emb_val = new embed_values_dec_struct_t;
-      emb_val->embval_array = static_cast<Record_Of_Type*>(get_at(0));
+      emb_val->embval_array = dynamic_cast<Record_Of_Type*>(get_at(0));
+      if (NULL == emb_val->embval_array) {
+        OPTIONAL<PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING>* embed_value = static_cast<OPTIONAL<PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING>*>(get_at(0));
+        embed_value->set_to_present();
+        emb_val->embval_array = static_cast<Record_Of_Type*>((*embed_value).get_opt_value());
+        emb_val_optional = true;
+      }
       emb_val->embval_array->set_size(0);
       emb_val->embval_index = 0;
     }
@@ -5334,7 +5499,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
               static_cast<Enum_Type*>(use_order->get_at(i - begin))
               ->from_int(in_dex);
               Base_Type *b = jumbled->get_at(k);
-              b->XER_decode(*jumbled->xer_descr(k), reader, flavor, emb_val);
+              b->XER_decode(*jumbled->xer_descr(k), reader, flavor, flavor2, emb_val);
               field_name_found = true;
               break;
             }
@@ -5360,7 +5525,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
                 static_cast<Enum_Type*>(use_order->get_at(i - begin))
                 ->from_int(in_dex);
                 Base_Type *b = jumbled->get_at(k);
-                b->XER_decode(*jumbled->xer_descr(k), reader, flavor, emb_val);
+                b->XER_decode(*jumbled->xer_descr(k), reader, flavor, flavor2, emb_val);
                 last_any_elem = k;
                 field_name_found = true;
                 break;
@@ -5445,12 +5610,12 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
                 optional_any_elem_check = opt_field->XER_check_any_elem(reader, next_field_name, tag_closed);
               }
             }
-            if (optional_any_elem_check) {
+            if (optional_any_elem_check && !already_processed) {
               int new_flavor = flavor ;
               if (i == field_cnt-1) new_flavor |= (p_td.xer_bits & USE_NIL);
               if (tag_closed)       new_flavor |= PARENT_CLOSED;
 
-              get_at(i)->XER_decode(*xer_descr(i), reader, new_flavor, emb_val);
+              get_at(i)->XER_decode(*xer_descr(i), reader, new_flavor, flavor2, emb_val);
             }
           }
           if (!get_at(i)->is_present()) {
@@ -5472,12 +5637,18 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
     } // if use-order
 
     if (0 != emb_val) {
+      bool all_unbound = true;
       static const UNIVERSAL_CHARSTRING emptystring(0, (const char*)NULL);
       for (int j = 0; j < emb_val->embval_index; ++j) {
         if (!emb_val->embval_array->get_at(j)->is_bound()) {
           emb_val->embval_array->get_at(j)->set_value(&emptystring);
+        }else if((static_cast<const UNIVERSAL_CHARSTRING*>(emb_val->embval_array->get_at(j)))->lengthof() !=0) {
+          all_unbound = false;
         }
       }
+      if(emb_val_optional && all_unbound){
+        static_cast<OPTIONAL<PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING>*>(get_at(0))->set_to_omit();
+      }
       delete emb_val;
     } // if embed-values
 
@@ -5537,8 +5708,12 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
   return 1; // decode successful
 }
 
-int Record_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
+int Record_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
 {
+  if (err_descr) {             
+    return JSON_encode_negtest(err_descr, p_td, p_tok);                
+  }
+
   if (!is_bound()) {
     TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
       "Encoding an unbound %s value.", is_set() ? "set" : "record");
@@ -5548,7 +5723,7 @@ int Record_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok
   int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
   
   int field_count = get_count();
-  for(int i = 0; i < field_count; ++i) {
+  for (int i = 0; i < field_count; ++i) {
     boolean metainfo_unbound = NULL != fld_descr(i)->json && fld_descr(i)->json->metainfo_unbound;
     if ((NULL != fld_descr(i)->json && fld_descr(i)->json->omit_as_null) || 
         get_at(i)->is_present() || metainfo_unbound) {
@@ -5572,6 +5747,106 @@ int Record_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok
   return enc_len;
 }
 
+int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
+                                     const TTCN_Typedescriptor_t& p_td,
+                                     JSON_Tokenizer& p_tok) const 
+{
+  if (!is_bound()) {
+    TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
+      "Encoding an unbound %s value.", is_set() ? "set" : "record");
+    return -1;
+  }
+  
+  int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+  
+  int values_idx = 0;
+  int edescr_idx = 0;
+  
+  int field_count = get_count();
+  for (int i = 0; i < field_count; ++i) {
+    if (-1 != p_err_descr->omit_before && p_err_descr->omit_before > i) {
+      continue;
+    }
+    
+    const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(i, values_idx);
+    const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(i, edescr_idx);
+    
+    if (NULL != err_vals && NULL != err_vals->before) {
+      if (NULL == err_vals->before->errval) {
+        TTCN_error("internal error: erroneous before value missing");
+      }
+      if (err_vals->before->raw) {
+        enc_len += err_vals->before->errval->JSON_encode_negtest_raw(p_tok);
+      } else {
+        if (NULL == err_vals->before->type_descr) {
+          TTCN_error("internal error: erroneous before typedescriptor missing");
+        }
+        // it's an extra field, so use the erroneous type's name as the field name
+        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, err_vals->before->type_descr->name);
+        enc_len += err_vals->before->errval->JSON_encode(*(err_vals->before->type_descr), p_tok);
+      }
+    }
+    
+    const char* field_name = (NULL != fld_descr(i)->json && NULL != fld_descr(i)->json->alias) ?
+      fld_descr(i)->json->alias : fld_name(i);
+    if (NULL != err_vals && NULL != err_vals->value) {
+      if (NULL != err_vals->value->errval) {
+        if (err_vals->value->raw) {
+          enc_len += err_vals->value->errval->JSON_encode_negtest_raw(p_tok);
+        } else {
+          if (NULL == err_vals->value->type_descr) {
+            TTCN_error("internal error: erroneous before typedescriptor missing");
+          }
+          // only replace the field's value, keep the field name
+          enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, field_name);
+          enc_len += err_vals->value->errval->JSON_encode(*(err_vals->value->type_descr), p_tok);
+        }
+      }
+    } else {
+      boolean metainfo_unbound = NULL != fld_descr(i)->json && fld_descr(i)->json->metainfo_unbound;
+      if ((NULL != fld_descr(i)->json && fld_descr(i)->json->omit_as_null) || 
+          get_at(i)->is_present() || metainfo_unbound) {
+        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, field_name);
+        if (metainfo_unbound && !get_at(i)->is_bound()) {
+          enc_len += p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL);
+          char* metainfo_str = mprintf("metainfo %s", field_name);
+          enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, metainfo_str);
+          Free(metainfo_str);
+          enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
+        }
+        else if (NULL != emb_descr) {
+          enc_len += get_at(i)->JSON_encode_negtest(emb_descr, *fld_descr(i), p_tok);
+        } else {
+          enc_len += get_at(i)->JSON_encode(*fld_descr(i), p_tok);
+        }
+      }
+    }
+    
+    if (NULL != err_vals && NULL != err_vals->after) {
+      if (NULL == err_vals->after->errval) {
+        TTCN_error("internal error: erroneous after value missing");
+      }
+      if (err_vals->after->raw) {
+        enc_len += err_vals->after->errval->JSON_encode_negtest_raw(p_tok);
+      } else {
+        if (NULL == err_vals->after->type_descr) {
+          TTCN_error("internal error: erroneous before typedescriptor missing");
+        }
+        // it's an extra field, so use the erroneous type's name as the field name
+        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, err_vals->after->type_descr->name);
+        enc_len += err_vals->after->errval->JSON_encode(*(err_vals->after->type_descr), p_tok);
+      }
+    }
+    
+    if (-1 != p_err_descr->omit_after && p_err_descr->omit_after <= i) {
+      break;
+    }
+  }
+  
+  enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+  return enc_len;
+}
+
 int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
 {
   json_token_t token = JSON_TOKEN_NONE;
@@ -5582,14 +5857,15 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
   }
   else if (JSON_TOKEN_OBJECT_START != token) {
     return JSON_ERROR_INVALID_TOKEN;
-  }
-  bound_flag = TRUE;
+  } 
   
   const int field_count = get_count();
   
   // initialize meta info states
   int* metainfo = new int[field_count];
+  boolean* field_found = new boolean[field_count];
   for (int i = 0; i < field_count; ++i) {
+    field_found[i] = FALSE;
     metainfo[i] = (NULL != fld_descr(i)->json && fld_descr(i)->json->metainfo_unbound) ?
       JSON_METAINFO_NONE : JSON_METAINFO_NOT_APPLICABLE;
   }
@@ -5629,6 +5905,7 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
         }
         if (strlen(expected_name) == name_len &&
             0 == strncmp(expected_name, name, name_len)) {
+          field_found[field_idx] = TRUE;
           break;
         }
       }
@@ -5716,7 +5993,7 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
       // no meta info was found for this field, report the delayed error
       JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name(field_idx));
     }
-    else if (!field->is_bound()) {
+    else if (!field_found[field_idx]) {
       if (NULL != fld_descr(field_idx)->json && NULL != fld_descr(field_idx)->json->default_value) {
         get_at(field_idx)->JSON_decode(*fld_descr(field_idx), DUMMY_BUFFER, p_silent);
       }
@@ -5729,7 +6006,7 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
     }
   }
   
-  delete metainfo;
+  delete[] metainfo;
   
   return dec_len;
 }
@@ -5919,7 +6196,7 @@ void Empty_Record_Type::decode(const TTCN_Typedescriptor_t& p_td,
     for (int success=reader.Read(); success==1; success=reader.Read()) {
       if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break;
     }
-    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, 0);
+    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, XER_NONE, 0);
     size_t bytes = reader.ByteConsumed();
     p_buf.set_pos(bytes);
     break;}
@@ -6042,7 +6319,7 @@ int Empty_Record_Type::XER_encode(const XERdescriptor_t& p_td,
 }
 
 int Empty_Record_Type::XER_decode(const XERdescriptor_t& p_td,
-  XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*)
+  XmlReaderWrap& reader, unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*)
 {
   int exer = is_exer(flavor);
   bound_flag = true;
This page took 0.040356 seconds and 5 git commands to generate.