-///////////////////////////////////////////////////////////////////////////////
-// 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"
#include "Charstring.hh"
#include "Universal_charstring.hh"
#include "Addfunc.hh"
+#include "PreGenRecordOf.hh"
////////////////////////////////////////////////////////////////////////////////
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
{
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
}
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,
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);
}
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);
}
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;
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;}
}
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;
// 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
}
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) {
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);
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);
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
}
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
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();
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);
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);
}
}
err_descr = other_record->err_descr;
- bound_flag = TRUE;
}
void Record_Type::encode(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;}
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);
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;
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
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;
// 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;
- (!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();
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);
}
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);
}
++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,
// 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;
// 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;
} //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)",
}
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
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();
// 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) {
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
}
/* * * * * * * * * 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())
{
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;
}
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
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,
}
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;
}
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;
}
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;
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()) {
} // 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
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");
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) {
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;
}
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;
}
}
if (strlen(expected_name) == name_len &&
0 == strncmp(expected_name, name, name_len)) {
+ field_found[field_idx] = TRUE;
break;
}
}
// 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);
}
}
}
- delete metainfo;
+ delete[] metainfo;
return dec_len;
}
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;}
}
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;