-///////////////////////////////////////////////////////////////////////////////
-// 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
+ * 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) const
+ const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
{
- return XER_encode(p_td, p_buf, flavor, indent); // ignore erroneous
+ return XER_encode(p_td, p_buf, flavor, indent, 0); // ignore erroneous
}
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
val_ptr = NULL;
}
else if (val_ptr->ref_count == 1) {
- if (refd_indices.empty()) {
+ if (NULL == refd_ind_ptr) {
for (int elem_count = 0; elem_count < val_ptr->n_elements; elem_count++) {
if (val_ptr->value_elements[elem_count] != NULL) {
delete val_ptr->value_elements[elem_count];
}
Record_Of_Type::Record_Of_Type(null_type /*other_value*/)
-: Base_Type(), val_ptr(new recordof_setof_struct), err_descr(NULL), max_refd_index(-1)
+: Base_Type(), val_ptr(new recordof_setof_struct), err_descr(NULL), refd_ind_ptr(NULL)
{
val_ptr->ref_count = 1;
val_ptr->n_elements = 0;
}
Record_Of_Type::Record_Of_Type(const Record_Of_Type& other_value)
-: Base_Type(other_value), val_ptr(NULL), err_descr(other_value.err_descr), max_refd_index(-1)
+: Base_Type(other_value), RefdIndexInterface(other_value)
+, val_ptr(NULL), err_descr(other_value.err_descr), refd_ind_ptr(NULL)
{
if (!other_value.is_bound())
TTCN_error("Copying an unbound record of/set of value.");
// Increment ref_count only if val_ptr is not NULL
if (other_value.val_ptr != NULL) {
- if (other_value.refd_indices.empty()) {
+ if (NULL == other_value.refd_ind_ptr) {
val_ptr = other_value.val_ptr;
val_ptr->ref_count++;
}
int Record_Of_Type::get_nof_elements() const
{
int nof_elements = (val_ptr != NULL) ? val_ptr->n_elements : 0;
- if (!refd_indices.empty()) {
+ if (NULL != refd_ind_ptr) {
while (nof_elements > 0) {
if (is_elem_bound(nof_elements - 1)) {
break;
int Record_Of_Type::get_max_refd_index()
{
- if (refd_indices.empty()) {
+ if (NULL == refd_ind_ptr) {
return -1;
}
- if (-1 == max_refd_index) {
- for (size_t i = 0; i < refd_indices.size(); ++i) {
- if (refd_indices[i] > max_refd_index) {
- max_refd_index = refd_indices[i];
+ if (-1 == refd_ind_ptr->max_refd_index) {
+ for (size_t i = 0; i < refd_ind_ptr->refd_indices.size(); ++i) {
+ if (refd_ind_ptr->refd_indices[i] > refd_ind_ptr->max_refd_index) {
+ refd_ind_ptr->max_refd_index = refd_ind_ptr->refd_indices[i];
}
}
}
- return max_refd_index;
+ return refd_ind_ptr->max_refd_index;
}
bool Record_Of_Type::is_index_refd(int index)
{
- for (size_t i = 0; i < refd_indices.size(); ++i) {
- if (index == refd_indices[i]) {
+ if (NULL == refd_ind_ptr) {
+ return false;
+ }
+ for (size_t i = 0; i < refd_ind_ptr->refd_indices.size(); ++i) {
+ if (index == refd_ind_ptr->refd_indices[i]) {
return true;
}
}
TTCN_error("Assigning an unbound value of type %s.",
other_value->get_descriptor()->name);
if (this != other_recof) {
- if (refd_indices.empty() && other_recof->refd_indices.empty()) {
+ if (NULL == refd_ind_ptr && NULL == other_recof->refd_ind_ptr) {
clean_up();
val_ptr = other_recof->val_ptr;
val_ptr->ref_count++;
boolean Record_Of_Type::is_bound() const
{
- if (refd_indices.empty()) {
+ if (NULL == refd_ind_ptr) {
return (val_ptr != NULL);
}
return (get_nof_elements() != 0);
}
return encoded_length;
}
- const TTCN_Typedescriptor_t* elem_descr = get_elem_descr();
+ const TTCN_Typedescriptor_t* elem_descr = p_td.oftype_descr;
for(int a=0;a<get_nof_elements();a++) {
if(a!=0 && p_td.text->separator_encode) {
buff.put_cs(*p_td.text->separator_encode);
}
if (emb_descr) {
encoded_length += get_at(a)->TEXT_encode_negtest(
- emb_descr,*get_elem_descr(),buff);
+ emb_descr,*p_td.oftype_descr,buff);
} else {
- encoded_length += get_at(a)->TEXT_encode(*get_elem_descr(),buff);
+ encoded_length += get_at(a)->TEXT_encode(*p_td.oftype_descr,buff);
}
need_separator=true;
}
while(TRUE){
Base_Type* val = create_elem();
pos=buff.get_pos();
- int len = val->TEXT_decode(*get_elem_descr(),buff,limit,TRUE);
+ int len = val->TEXT_decode(*p_td.oftype_descr,buff,limit,TRUE);
if(len==-1 || (len==0 && !limit.has_token())){
buff.set_pos(pos);
delete val;
break;
}
sep_found=FALSE;
- if (refd_indices.empty()) {
+ 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;
TTCN_EncDec_ErrorContext ec;
for(int elem_i=0; elem_i<get_nof_elements(); elem_i++) {
ec.set_msg("Component #%d: ", elem_i);
- new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV(*get_elem_descr(), p_coding));
+ new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV(*p_td.oftype_descr, p_coding));
}
if (is_set()) new_tlv->sort_tlvs();
}
ec.set_msg("Component #%d: ", elem_i);
if (emb_descr) {
new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV_negtest(
- emb_descr, *get_elem_descr(), p_coding));
+ emb_descr, *p_td.oftype_descr, p_coding));
} else {
new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV(
- *get_elem_descr(), p_coding));
+ *p_td.oftype_descr, p_coding));
}
}
TTCN_EncDec_ErrorContext ec_1("Component #");
TTCN_EncDec_ErrorContext ec_2("0: ");
while(BER_decode_constdTLV_next(stripped_tlv, V_pos, L_form, tmp_tlv)) {
- get_at(get_nof_elements())->BER_decode_TLV(*get_elem_descr(), tmp_tlv, L_form);
+ get_at(get_nof_elements())->BER_decode_TLV(*p_td.oftype_descr, tmp_tlv, L_form);
ec_2.set_msg("%d: ", val_ptr->n_elements);
}
return TRUE;
set_size(0);
}
int start_field = get_nof_elements(); // append at the end
- TTCN_Typedescriptor_t const& elem_descr = *get_elem_descr();
+ TTCN_Typedescriptor_t const& elem_descr = *p_td.oftype_descr;
if (p_td.raw->fieldlength || sel_field != -1) {
if (sel_field == -1) sel_field = p_td.raw->fieldlength;
for (int a = 0; a < sel_field; a++) {
if (!first_call) return -1;
goto finished;
}
- int ext_bit = rawdec_ebv();
while (limit > 0) {
start_of_field = buff.get_pos_bit();
Base_Type* field_bt = get_at(a); // non-const, extend the record-of
decoded_length += decoded_field_length;
limit -= decoded_field_length;
a++;
- if (ext_bit != 1/*XDEFNO*/&& ext_bit != -1/*XDEFDEFAULT*/) {
- // ext_bit here may be 2 (XDEFYES) or 3 (XDEFREVERSE).
- // (ext_bit != 2) is 0 or 1
+ if (EXT_BIT_NO != p_td.raw->extension_bit) {
+ // (EXT_BIT_YES != p_td.raw->extension_bit) is 0 or 1
// This is the opposite value of what the bit needs to be to signal
// the end of decoding, because x-or is the equivalent of !=
- if ((ext_bit != 2/*XDEFYES*/) ^ buff.get_last_bit()) {
+ if ((EXT_BIT_YES != p_td.raw->extension_bit) ^ buff.get_last_bit()) {
goto finished;
}
}
myleaf.rec_of = TRUE;
myleaf.body.node.num_of_nodes = encoded_num_of_records;
myleaf.body.node.nodes = init_nodes_of_enc_tree(encoded_num_of_records);
- TTCN_Typedescriptor_t const& elem_descr = *get_elem_descr();
+ TTCN_Typedescriptor_t const& elem_descr = *p_td.oftype_descr;
for (int a = 0; a < encoded_num_of_records; a++) {
const Base_Type *field_bt = get_at(a);
myleaf.body.node.nodes[a] = new RAW_enc_tree(TRUE, &myleaf, &(myleaf.curr_pos), a, elem_descr.raw);
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);
- TTCN_Typedescriptor_t const& elem_descr = *get_elem_descr();
+ TTCN_Typedescriptor_t const& elem_descr = *p_td.oftype_descr;
if (err_vals && err_vals->before) {
if (err_vals->before->errval == NULL)
TTCN_error("internal error: erroneous before value missing");
myleaf.body.node.nodes[node_pos] = new RAW_enc_tree(TRUE, &myleaf,
&(myleaf.curr_pos), node_pos, elem_descr.raw);
encoded_length += get_at(i)->RAW_encode_negtest(emb_descr,
- *get_elem_descr(), *myleaf.body.node.nodes[node_pos++]);
+ *p_td.oftype_descr, *myleaf.body.node.nodes[node_pos++]);
} else {
myleaf.body.node.nodes[node_pos] = new RAW_enc_tree(TRUE, &myleaf,
&(myleaf.curr_pos), node_pos, elem_descr.raw);
- encoded_length += get_at(i)->RAW_encode(*get_elem_descr(),
+ encoded_length += get_at(i)->RAW_encode(*p_td.oftype_descr,
*myleaf.body.node.nodes[node_pos++]);
}
}
return myleaf.length = encoded_length;
}
-int Record_Of_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
+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");
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(*get_elem_descr(), p_tok);
- if (0 > ret_val) break;
- enc_len += ret_val;
+ 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,
+ "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);
+
+ 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(*get_elem_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);
}
return JSON_ERROR_FATAL;
}
- if (refd_indices.empty()) {
+ 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;
case TTCN_EncDec::CT_XER: {
TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
unsigned XER_coding=va_arg(pvar, unsigned);
- XER_encode(*(p_td.xer),p_buf, XER_coding, 0);
+ XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0);
p_buf.put_c('\n');
break;}
case TTCN_EncDec::CT_JSON: {
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);
+ XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, XER_NONE, 0);
size_t bytes = reader.ByteConsumed();
p_buf.set_pos(bytes);
break;}
if (val_ptr) for (int i = 0; i < get_nof_elements(); ++i) {
size_t num_new = 0;
char **new_namespaces = get_at(i)->collect_ns(
- *get_elem_descr()->xer, num_new, def_ns_1);
+ *p_td.oftype_descr, num_new, def_ns_1);
merge_ns(collected_ns, num_collected, new_namespaces, num_new);
def_ns = def_ns || def_ns_1; // alas, no ||=
}
static const universal_char tb = { 0,0,0,9 };
int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
- unsigned int flavor, int indent) const
+ unsigned int flavor, int indent, embed_values_enc_struct_t* emb_val) const
{
if (err_descr) {
- return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent);
+ return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent, emb_val);
}
if (val_ptr == 0) TTCN_error(
check_namespace_restrictions(p_td, (const char*)cs);
}
before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf,
- flavor | ANY_ATTRIBUTES, indent);
+ flavor | ANY_ATTRIBUTES, indent, 0);
p_buf.put_c('\'');
p_buf.put_c(' ');
UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(*elem) + j);
after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf,
- flavor | ANY_ATTRIBUTES, indent);
+ flavor | ANY_ATTRIBUTES, indent, 0);
// Put this attribute in a dummy element and walk through it to check its validity
TTCN_Buffer check_buf;
}
else { // not ANY-ATTRIBUTES
unsigned int sub_flavor = flavor | XER_RECOF | (p_td.xer_bits & (XER_LIST));
+ TTCN_EncDec_ErrorContext ec_0("Index ");
+ TTCN_EncDec_ErrorContext ec_1;
for (int i = 0; i < nof_elements; ++i) {
+ if (i > 0 && !own_tag && 0 != emb_val &&
+ emb_val->embval_index < emb_val->embval_array->size_of()) {
+ emb_val->embval_array->get_at(emb_val->embval_index)->XER_encode(
+ UNIVERSAL_CHARSTRING_xer_, p_buf, flavor | EMBED_VALUES, indent+1, 0);
+ ++emb_val->embval_index;
+ }
+ ec_1.set_msg("%d: ", i);
if (exer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');
- get_at(i)->XER_encode(*get_elem_descr()->xer, p_buf,
- sub_flavor, indent+own_tag);
+ get_at(i)->XER_encode(*p_td.oftype_descr, p_buf,
+ sub_flavor, indent+own_tag, emb_val);
}
if (indenting && nof_elements && !is_exerlist(flavor)) {
* @param indent indentation level
* @return number of bytes generated
*/
-int Record_Of_Type::encode_element(int i,
+int Record_Of_Type::encode_element(int i, const XERdescriptor_t& p_td,
const Erroneous_values_t* ev, const Erroneous_descriptor_t* ed,
- TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent) const
+ TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent, embed_values_enc_struct_t* emb_val) const
{
int enc_len = p_buf.get_len();
TTCN_EncDec_ErrorContext ec;
if (ev->before->type_descr==NULL) TTCN_error(
"internal error: erroneous before type descriptor missing");
ev->before->errval->XER_encode(*ev->before->type_descr->xer,
- p_buf, sub_flavor, indent);
+ p_buf, sub_flavor, indent, 0);
}
}
if (ev->value->type_descr==NULL) TTCN_error(
"internal error: erroneous value type descriptor missing");
ev->value->errval->XER_encode(*ev->value->type_descr->xer,
- p_buf, sub_flavor, indent);
+ p_buf, sub_flavor, indent, 0);
}
} // else -> omit
} else {
ec.set_msg("Component #%d: ", i);
if (ed) {
- get_at(i)->XER_encode_negtest(ed, *get_elem_descr()->xer, p_buf, sub_flavor, indent);
+ get_at(i)->XER_encode_negtest(ed, p_td, p_buf, sub_flavor, indent, emb_val);
} else {
// the "real" encoder
- get_at(i)->XER_encode(*get_elem_descr()->xer, p_buf, sub_flavor, indent);
+ get_at(i)->XER_encode(p_td, p_buf, sub_flavor, indent, emb_val);
}
}
if (ev->after->type_descr==NULL) TTCN_error(
"internal error: erroneous after type descriptor missing");
ev->after->errval->XER_encode(*ev->after->type_descr->xer,
- p_buf, sub_flavor, indent);
+ p_buf, sub_flavor, indent, 0);
}
}
// XERSTUFF Record_Of_Type::XER_encode_negtest
int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
- const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned flavor, int indent) const
+ const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned flavor, int indent,
+ embed_values_enc_struct_t* emb_val) const
{
if (val_ptr == 0) TTCN_error(
"Attempt to XER-encode an unbound record of type %s", get_descriptor()->name);
if (ev->before->type_descr==NULL) TTCN_error(
"internal error: erroneous before type descriptor missing");
else ev->before->errval->XER_encode(*ev->before->type_descr->xer,
- p_buf, flavor, indent);
+ p_buf, flavor, indent, 0);
}
}
if (ev->value->type_descr==NULL) TTCN_error(
"internal error: erroneous value type descriptor missing");
else ev->value->errval->XER_encode(*ev->value->type_descr->xer,
- p_buf, flavor, indent);
+ p_buf, flavor, indent, 0);
}
}
}
UNIVERSAL_CHARSTRING before(sp_at, (const universal_char*)(*elem));
before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf,
- flavor | ANY_ATTRIBUTES, indent);
+ flavor | ANY_ATTRIBUTES, indent, 0);
p_buf.put_c('\'');
p_buf.put_c(' ');
UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(*elem) + j);
after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf,
- flavor | ANY_ATTRIBUTES, indent);
+ flavor | ANY_ATTRIBUTES, indent, 0);
}
}
if (ev->after->type_descr==NULL) TTCN_error(
"internal error: erroneous after type descriptor missing");
else ev->after->errval->XER_encode(*ev->after->type_descr->xer,
- p_buf, flavor, indent);
+ p_buf, flavor, indent, 0);
}
}
}
for (int i = 0; i < nof_elements; ++i) {
if (i < p_err_descr->omit_before) continue;
+
+ if (0 != emb_val && i > 0 && !own_tag &&
+ emb_val->embval_index < emb_val->embval_array->size_of()) {
+ const Erroneous_values_t * ev0_i = NULL;
+ const Erroneous_descriptor_t* ed0_i = NULL;
+ if (emb_val->embval_err) {
+ ev0_i = emb_val->embval_err->next_field_err_values(emb_val->embval_index, emb_val->embval_err_val_idx);
+ ed0_i = emb_val->embval_err->next_field_emb_descr (emb_val->embval_index, emb_val->embval_err_descr_idx);
+ }
+ emb_val->embval_array->encode_element(emb_val->embval_index, UNIVERSAL_CHARSTRING_xer_,
+ ev0_i, ed0_i, p_buf, flavor | EMBED_VALUES, indent + own_tag, 0);
+ ++emb_val->embval_index;
+ }
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);
- encode_element(i, err_vals, emb_descr, p_buf, sub_flavor, indent+own_tag);
+ encode_element(i, *p_td.oftype_descr, err_vals, emb_descr, p_buf, sub_flavor, indent+own_tag, emb_val);
// omit_after value -1 becomes "very big"
if ((unsigned int)i >= (unsigned int)p_err_descr->omit_after) break;
}
int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
- XmlReaderWrap& reader, unsigned int flavor)
+ 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;
pos += strlen(str) + 1;
// Construct a new XML Reader with the current token.
TTCN_Buffer buf2;
- const XERdescriptor_t& sub_xer = *get_elem_descr()->xer;
+ const XERdescriptor_t& sub_xer = *p_td.oftype_descr;
buf2.put_c('<');
write_ns_prefix(sub_xer, buf2);
// 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);
+ 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
* belong to the embedded type, the record-of has already ended. */
if (!own_tag && !can_start_v(
(const char*)reader.LocalName(), (const char*)reader.NamespaceUri(),
- *get_elem_descr()->xer, flavor | UNTAGGED))
+ p_td, flavor | UNTAGGED))
{
for (; success == 1 && reader.Depth() > depth; success = reader.Read()) ;
// We should now be back at the same depth as we started.
}
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(*get_elem_descr()->xer, reader, flavor);
+ 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) {
}
break;
}
+ else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && get_nof_elements() > 0) {
+ UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
+ emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+ success = reader.Read();
+ }
else {
success = reader.Read();
}
} /* next read */
} /* if not empty element */
} /* if not LIST */
+ if (!own_tag && exer && (p_td.xer_bits & XER_OPTIONAL) && get_nof_elements() == 0) {
+ // set it to unbound, so the OPTIONAL class sets it to omit
+ clean_up();
+ }
return 1; // decode successful
}
}
param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, is_set()?"set of value":"record of value");
+
+ Module_Param_Ptr mp = ¶m;
+ if (param.get_type() == Module_Param::MP_Reference) {
+ mp = param.get_referenced_param();
+ }
+
switch (param.get_operation_type()) {
case Module_Param::OT_ASSIGN:
- if (param.get_type()==Module_Param::MP_Value_List && param.get_size()==0) {
+ if (mp->get_type()==Module_Param::MP_Value_List && mp->get_size()==0) {
set_val(NULL_VALUE);
return;
}
- switch (param.get_type()) {
+ switch (mp->get_type()) {
case Module_Param::MP_Value_List:
- set_size(param.get_size());
- for (size_t i=0; i<param.get_size(); ++i) {
- Module_Param* const curr = param.get_elem(i);
+ set_size(mp->get_size());
+ for (size_t i=0; i<mp->get_size(); ++i) {
+ Module_Param* const curr = mp->get_elem(i);
if (curr->get_type()!=Module_Param::MP_NotUsed) {
get_at(i)->set_param(*curr);
}
}
break;
case Module_Param::MP_Indexed_List:
- for (size_t i=0; i<param.get_size(); ++i) {
- Module_Param* const current = param.get_elem(i);
+ for (size_t i=0; i<mp->get_size(); ++i) {
+ Module_Param* const current = mp->get_elem(i);
get_at(current->get_id()->get_index())->set_param(*current);
}
break;
}
break;
case Module_Param::OT_CONCAT:
- switch (param.get_type()) {
+ switch (mp->get_type()) {
case Module_Param::MP_Value_List: {
if (!is_bound()) set_val(NULL_VALUE);
int start_idx = lengthof();
- for (size_t i=0; i<param.get_size(); ++i) {
- Module_Param* const curr = param.get_elem(i);
+ for (size_t i=0; i<mp->get_size(); ++i) {
+ Module_Param* const curr = mp->get_elem(i);
if ((curr->get_type()!=Module_Param::MP_NotUsed)) {
get_at(start_idx+(int)i)->set_param(*curr);
}
}
}
+Module_Param* Record_Of_Type::get_param(Module_Param_Name& param_name) const
+{
+ if (!is_bound()) {
+ return new Module_Param_Unbound();
+ }
+ if (param_name.next_name()) {
+ // Haven't reached the end of the module parameter name
+ // => the name refers to one of the elements, not to the whole record of
+ char* param_field = param_name.get_current_name();
+ if (param_field[0] < '0' || param_field[0] > '9') {
+ TTCN_error("Unexpected record field name in module parameter reference, "
+ "expected a valid index for %s type `%s'",
+ is_set() ? "set of" : "record of", get_descriptor()->name);
+ }
+ int param_index = -1;
+ sscanf(param_field, "%d", ¶m_index);
+ return get_at(param_index)->get_param(param_name);
+ }
+ Vector<Module_Param*> values;
+ for (int i = 0; i < val_ptr->n_elements; ++i) {
+ values.push_back(val_ptr->value_elements[i]->get_param(param_name));
+ }
+ Module_Param_Value_List* mp = new Module_Param_Value_List();
+ mp->add_list_with_implicit_ids(&values);
+ values.clear();
+ return mp;
+}
+
void Record_Of_Type::set_implicit_omit()
{
for (int i = 0; i < get_nof_elements(); ++i) {
void Record_Of_Type::add_refd_index(int index)
{
- refd_indices.push_back(index);
+ if (NULL == refd_ind_ptr) {
+ refd_ind_ptr = new refd_index_struct;
+ refd_ind_ptr->max_refd_index = -1;
+ }
+ refd_ind_ptr->refd_indices.push_back(index);
if (index > get_max_refd_index()) {
- max_refd_index = index;
+ refd_ind_ptr->max_refd_index = index;
}
}
void Record_Of_Type::remove_refd_index(int index)
{
- for (size_t i = refd_indices.size(); i > 0; --i) {
- if (refd_indices[i - 1] == index) {
- refd_indices.erase_at(i - 1);
+ for (size_t i = refd_ind_ptr->refd_indices.size(); i > 0; --i) {
+ if (refd_ind_ptr->refd_indices[i - 1] == index) {
+ refd_ind_ptr->refd_indices.erase_at(i - 1);
break;
}
}
- if (get_max_refd_index() == index) {
- max_refd_index = -1;
+ if (refd_ind_ptr->refd_indices.empty()) {
+ delete refd_ind_ptr;
+ refd_ind_ptr = NULL;
+ }
+ else if (get_max_refd_index() == index) {
+ refd_ind_ptr->max_refd_index = -1;
}
}
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
}
param.basic_check(Module_Param::BC_VALUE, is_set()?"set value":"record value");
- switch (param.get_type()) {
+
+ Module_Param_Ptr mp = ¶m;
+ if (param.get_type() == Module_Param::MP_Reference) {
+ mp = param.get_referenced_param();
+ }
+
+ switch (mp->get_type()) {
case Module_Param::MP_Value_List:
- if (get_count()<(int)param.get_size()) {
- param.error("%s value of type %s has %d fields but list value has %d fields", is_set()?"Set":"Record", get_descriptor()->name, get_count(), (int)param.get_size());
+ if (get_count()<(int)mp->get_size()) {
+ param.error("%s value of type %s has %d fields but list value has %d fields", is_set()?"Set":"Record", get_descriptor()->name, get_count(), (int)mp->get_size());
}
- for (size_t i=0; i<param.get_size(); i++) {
- Module_Param* mp = param.get_elem(i);
- if (mp->get_type()!=Module_Param::MP_NotUsed) {
- get_at((int)i)->set_param(*mp);
+ for (size_t i=0; i<mp->get_size(); i++) {
+ Module_Param* mp_elem = mp->get_elem(i);
+ if (mp_elem->get_type()!=Module_Param::MP_NotUsed) {
+ get_at((int)i)->set_param(*mp_elem);
}
}
break;
case Module_Param::MP_Assignment_List:
- for (size_t i=0; i<param.get_size(); ++i) {
- Module_Param* const current = param.get_elem(i);
+ for (size_t i=0; i<mp->get_size(); ++i) {
+ Module_Param* const current = mp->get_elem(i);
bool found = false;
for (int j=0; j<get_count(); ++j) {
if (!strcmp(fld_name(j), current->get_id()->get_name())) {
}
}
+Module_Param* Record_Type::get_param(Module_Param_Name& param_name) const
+{
+ if (!is_bound()) {
+ return new Module_Param_Unbound();
+ }
+ if (param_name.next_name()) {
+ // Haven't reached the end of the module parameter name
+ // => the name refers to one of the fields, not to the whole record
+ char* param_field = param_name.get_current_name();
+ if (param_field[0] >= '0' && param_field[0] <= '9') {
+ TTCN_error("Unexpected array index in module parameter reference, "
+ "expected a valid field name for %s type `%s'",
+ is_set() ? "set" : "record", get_descriptor()->name);
+ }
+ int field_cnt = get_count();
+ for (int field_idx = 0; field_idx < field_cnt; field_idx++) {
+ if (strcmp(fld_name(field_idx), param_field) == 0) {
+ return get_at(field_idx)->get_param(param_name);
+ }
+ }
+ TTCN_error("Field `%s' not found in %s type `%s'",
+ param_field, is_set() ? "set" : "record", get_descriptor()->name);
+ }
+ Module_Param_Assignment_List* mp = new Module_Param_Assignment_List();
+ for (int i = 0; i < get_count(); ++i) {
+ Module_Param* mp_field = get_at(i)->get_param(param_name);
+ mp_field->set_id(new Module_Param_FieldName(mcopystr(fld_name(i))));
+ mp->add_elem(mp_field);
+ }
+ return mp;
+}
+
void Record_Type::set_implicit_omit()
{
int field_cnt = get_count();
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,
case TTCN_EncDec::CT_XER: {
TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
unsigned XER_coding=va_arg(pvar, unsigned);
- XER_encode(*(p_td.xer),p_buf, XER_coding, 0);
+ XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0);
p_buf.put_c('\n');
break;}
case TTCN_EncDec::CT_JSON: {
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);
+ 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;
}
int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
- unsigned int flavor, int indent) const
+ unsigned int flavor, int indent, embed_values_enc_struct_t*) const
{
if (err_descr) {
- return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent);
+ return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent, 0);
}
if (!is_bound()) {
TTCN_EncDec_ErrorContext::error
// 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();
const Base_Type * const q_uri = get_at(0);
if (q_uri->is_present()) {
p_buf.put_s(11, (cbyte*)" xmlns:b0='");
- q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1);
+ q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1, 0);
p_buf.put_c('\'');
}
sub_len += 3;
}
const Base_Type* const q_name = get_at(1);
- sub_len += q_name->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1);
+ sub_len += q_name->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1, 0);
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);
+ sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1, 0);
}
if (!exer && (p_td.xer_bits & USE_ORDER)) {
// The USE-ORDER member as an ordinary record of enumerated
- sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1);
+ sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1, 0);
}
if (exer && (indent==0 || (flavor & DEF_NS_SQUASHED))) // write namespaces for toplevel only
for (i = start_at; i < first_nonattr; ++i) {
boolean is_xer_attr_field = xer_descr(i)->xer_bits & XER_ATTRIBUTE;
ec_1.set_msg("%s': ", fld_name(i)); // attr
- int tmp_len = get_at(i)->XER_encode(*xer_descr(i), p_buf, flavor, indent+1);
+ int tmp_len = get_at(i)->XER_encode(*xer_descr(i), p_buf, flavor, indent+1, 0);
if (is_xer_attr_field && !exer) sub_len += tmp_len; /* do not add if attribute and EXER */
}
p_buf.put_s(start_tag_len , (cbyte*)">\n");
}
- int expected_embed = (field_cnt - first_nonattr + 1);
if (exer && (p_td.xer_bits & EMBED_VALUES)) {
- ec_1.set_msg("%s': ", fld_name(0));
- int num_opt;
- if ((p_td.xer_bits & USE_NIL) && !get_at(field_cnt-1)->ispresent()) {
- expected_embed = 0; //25.2.6 a
- }
- else if ((num_opt = optional_count())) {
- const int * optionals = get_optional_indexes();
- for (int opt_idx = 0; opt_idx < num_opt; ++opt_idx) {
- // skip optional attributes
- if (optionals[opt_idx] < start_at + num_attributes) continue;
- // reduce for each omitted member
- if (!get_at(optionals[opt_idx])->is_present()) --expected_embed;
- }
- }
- // Check the correct number of EMBED-VALUES (regular non-attributes + 1)
- if (embed_values->size_of() != expected_embed)
- TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,
- "Wrong number %d of EMBED-VALUEs, expected %d",
- embed_values->size_of(), expected_embed);
/* write the first string */
- if (expected_embed > 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);
+ 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,
* pseudo-members for USE-ORDER, etc.) */
// early_to_bed can only be true if exer is true (transitive through nil_attribute)
- if (!early_to_bed) for ( i = begin; i < end; ++i ) {
- const Base_Type *uoe = 0; // "useOrder enum"
- const Enum_Type *enm = 0; // the enum value selecting the field
- if (exer && use_order) {
- uoe = use_order->get_at(i - begin);
- enm = static_cast<const Enum_Type *>(uoe);
- }
-
- // "actual" index, may be perturbed by USE-ORDER
- int ai = !(exer && (p_td.xer_bits & USE_ORDER)) ? i :
- enm->as_int() + useorder_base;
- ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr
-
- const XERdescriptor_t& descr = *ordered->xer_descr(ai);
- sub_len += ordered->get_at(ai)->XER_encode(descr, p_buf,
- // Pass USE-NIL to the last field (except when USE-ORDER is also in effect,
- // because the tag-stripping effect of USE-NIL has been achieved
- // by encoding the sub-fields directly).
- flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0),
- indent+!omit_tag);
-
- // Now the next embed-values string (NOT affected by USE-ORDER!)
- if (exer && (p_td.xer_bits & EMBED_VALUES) && (i - begin + 1) < expected_embed) {
- embed_values->get_at(i - begin + 1)->XER_encode(UNIVERSAL_CHARSTRING_xer_
- , p_buf, flavor | EMBED_VALUES, indent+1);
- }
- } //for
+ if (!early_to_bed) {
+ embed_values_enc_struct_t* emb_val = 0;
+ 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;
+ emb_val->embval_err = 0;
+ }
+
+ for ( i = begin; i < end; ++i ) {
+ const Base_Type *uoe = 0; // "useOrder enum"
+ const Enum_Type *enm = 0; // the enum value selecting the field
+ if (exer && use_order) {
+ uoe = use_order->get_at(i - begin);
+ enm = static_cast<const Enum_Type *>(uoe);
+ }
+
+ // "actual" index, may be perturbed by USE-ORDER
+ int ai = !(exer && (p_td.xer_bits & USE_ORDER)) ? i :
+ enm->as_int() + useorder_base;
+ ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr
+
+ const XERdescriptor_t& descr = *ordered->xer_descr(ai);
+ sub_len += ordered->get_at(ai)->XER_encode(descr, p_buf,
+ // Pass USE-NIL to the last field (except when USE-ORDER is also in effect,
+ // because the tag-stripping effect of USE-NIL has been achieved
+ // by encoding the sub-fields directly).
+ flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0),
+ indent+!omit_tag, emb_val);
+
+ // Now the next embed-values string (NOT affected by USE-ORDER!)
+ if (exer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&
+ 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 (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)",
+ embed_values->size_of(), emb_val->embval_index);
+ }
+ delete emb_val;
+ }
+ } // if (!early_to_bed)
} // if (QNAME)
if (!omit_tag) {
*/
int Record_Type::encode_field(int i,
const Erroneous_values_t* err_vals, const Erroneous_descriptor_t* emb_descr,
- TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent) const
+ TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent, embed_values_enc_struct_t* emb_val) const
{
int enc_len = 0;
TTCN_EncDec_ErrorContext ec;
if (err_vals->before->type_descr==NULL) TTCN_error(
"internal error: erroneous before typedescriptor missing");
enc_len += err_vals->before->errval->XER_encode(
- *err_vals->before->type_descr->xer, p_buf, sub_flavor, indent);
+ *err_vals->before->type_descr->xer, p_buf, sub_flavor, indent, 0);
}
}
if (err_vals->value->type_descr==NULL) TTCN_error(
"internal error: erroneous value typedescriptor missing");
enc_len += err_vals->value->errval->XER_encode(
- *err_vals->value->type_descr->xer, p_buf, sub_flavor, indent);
+ *err_vals->value->type_descr->xer, p_buf, sub_flavor, indent, 0);
}
} // else -> omit
} else {
ec.set_msg("Component %s: ", fld_name(i));
if (emb_descr) {
enc_len += get_at(i)->XER_encode_negtest(emb_descr, *xer_descr(i), p_buf,
- sub_flavor, indent);
+ sub_flavor, indent, emb_val);
} else {
// the "real" encoder
enc_len += get_at(i)->XER_encode(*xer_descr(i), p_buf,
- sub_flavor, indent);
+ sub_flavor, indent, emb_val);
}
}
if (err_vals->after->type_descr==NULL) TTCN_error(
"internal error: erroneous after typedescriptor missing");
enc_len += err_vals->after->errval->XER_encode(
- *err_vals->after->type_descr->xer, p_buf, sub_flavor, indent);
+ *err_vals->after->type_descr->xer, p_buf, sub_flavor, indent, 0);
}
}
// XERSTUFF Record_Type::XER_encode_negtest
int Record_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) const
+ const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent,
+ embed_values_enc_struct_t*) const
{
if (!is_bound()) {
TTCN_EncDec_ErrorContext::error
if (ev->before->type_descr==NULL) TTCN_error(
"internal error: erroneous before typedescriptor missing");
sub_len += ev->before->errval->XER_encode(
- *ev->before->type_descr->xer, p_buf, flavor, indent);
+ *ev->before->type_descr->xer, p_buf, flavor, indent, 0);
}
}
if (ev->value->type_descr==NULL) TTCN_error(
"internal error: erroneous value typedescriptor missing");
sub_len += ev->value->errval->XER_encode(
- *ev->value->type_descr->xer, p_buf, flavor, indent);
+ *ev->value->type_descr->xer, p_buf, flavor, indent, 0);
}
} // else -> omit
} else {
// the "real" encoder
if (q_uri->is_present()) {
p_buf.put_s(11, (cbyte*)" xmlns:b0='");
- sub_len += q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1);
+ sub_len += q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1, 0);
p_buf.put_c('\'');
}
}
if (ev->after->type_descr==NULL) TTCN_error(
"internal error: erroneous after typedescriptor missing");
sub_len += ev->after->errval->XER_encode(
- *ev->after->type_descr->xer, p_buf, flavor, indent);
+ *ev->after->type_descr->xer, p_buf, flavor, indent, 0);
}
}
if (ev->before->type_descr==NULL) TTCN_error(
"internal error: erroneous before typedescriptor missing");
sub_len += ev->before->errval->XER_encode(
- *ev->before->type_descr->xer, p_buf, flavor, indent);
+ *ev->before->type_descr->xer, p_buf, flavor, indent, 0);
}
}
if (ev->value->type_descr==NULL) TTCN_error(
"internal error: erroneous value typedescriptor missing");
sub_len += ev->value->errval->XER_encode(
- *ev->value->type_descr->xer, p_buf, flavor, indent);
+ *ev->value->type_descr->xer, p_buf, flavor, indent, 0);
}
} // else -> omit
} else {
sub_len += 3;
}
- sub_len += get_at(1)->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1);
+ sub_len += get_at(1)->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1, 0);
}
}
if (ev->after->type_descr==NULL) TTCN_error(
"internal error: erroneous after typedescriptor missing");
sub_len += ev->after->errval->XER_encode(
- *ev->after->type_descr->xer, p_buf, flavor, indent);
+ *ev->after->type_descr->xer, p_buf, flavor, indent, 0);
}
}
else { // not USE-QNAME
if (!exer && (p_td.xer_bits & EMBED_VALUES)) {
// The EMBED-VALUES member as an ordinary record of string
- sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1);
+ sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1, 0);
}
if (!exer && (p_td.xer_bits & USE_ORDER)) {
// The USE-ORDER member as an ordinary record of enumerated
- sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1);
+ sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1, 0);
}
if (exer && (indent==0 || (flavor & DEF_NS_SQUASHED))) // write namespaces for toplevel only
boolean is_xer_attr_field = xer_descr(i)->xer_bits & XER_ATTRIBUTE;
ec_1.set_msg("%s': ", fld_name(i)); // attr
- tmp_len = encode_field(i, ev, ed, p_buf, flavor, indent + !omit_tag);
+ tmp_len = encode_field(i, ev, ed, p_buf, flavor, indent + !omit_tag, 0);
if (is_xer_attr_field && !exer) sub_len += tmp_len; // do not add if attribute and EXER
int embed_values_val_idx = 0;
int embed_values_descr_idx = 0;
- int expected_embed = (field_cnt - first_nonattr + 1);
if (exer && (p_td.xer_bits & EMBED_VALUES)) {
ed0 = p_err_descr->next_field_emb_descr(0, edescr_idx);
- ec_1.set_msg("%s': ", fld_name(0));
- int num_opt;
- if ((p_td.xer_bits & USE_NIL) && !get_at(field_cnt-1)->ispresent()) {
- expected_embed = 0; //25.2.6 a
- }
- else if ((num_opt = optional_count()) > 0) {
- const int * optionals = get_optional_indexes();
- for (int opt_idx = 0; opt_idx < num_opt; ++opt_idx) {
- // skip optional attributes
- if (optionals[opt_idx] < start_at + num_attributes) continue;
- // reduce for each omitted member
- if (!get_at(optionals[opt_idx])->is_present()) --expected_embed;
- }
- }
- // Check the correct number of EMBED-VALUES (regular non-attributes + 1)
- if (embed_values->size_of() != expected_embed)
- TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,
- "Wrong number %d of EMBED-VALUEs, expected %d",
- embed_values->size_of(), expected_embed);
// write the first string
- if (expected_embed > 0) {
+ if (embed_values->size_of() > 0) {
const Erroneous_values_t * ev0_0 = NULL;
const Erroneous_descriptor_t* ed0_0 = NULL;
if (ed0) {
ev0_0 = ed0->next_field_err_values(0, embed_values_val_idx);
ed0_0 = ed0->next_field_emb_descr (0, embed_values_descr_idx);
}
- sub_len += embed_values->encode_element(0, ev0_0, ed0_0,
- p_buf, flavor | EMBED_VALUES, indent+!omit_tag);
+ sub_len += embed_values->encode_element(0, UNIVERSAL_CHARSTRING_xer_,
+ ev0_0, ed0_0, p_buf, flavor | EMBED_VALUES, indent+!omit_tag, 0);
}
}
// fields of this record; and the USE_ORDER case (with or without USE-NIL).
//
// early_to_bed can only be true if exer is true (transitive through nil_attribute)
- if (!early_to_bed) for ( i = begin; i < end; ++i ) {
-
- const Base_Type *uoe = 0; // "useOrder enum"
- const Enum_Type *enm = 0; // the enum value selecting the field
-
- // "actual" index, may be perturbed by USE-ORDER.
- // We use this value to index the appropriate record.
- int ai = i;
-
- const Erroneous_values_t * ev = NULL;
- const Erroneous_descriptor_t* ed = NULL;
- if (exer && use_order) {
- // If USE-ORDER is in effect, it introduces a level of indirection
- // into the indexing of fields: "i" is used to select an element
- // of the use_order member (an enum), whose value is used to select
- // the field being encoded.
- uoe = use_order->get_at(i - begin);
- enm = static_cast<const Enum_Type *>(uoe);
- ai = enm->as_int() + useorder_base;
-
- // Because it is not guaranteed that ai will increase monotonically,
- // we can't use next_field_...().
- ev = p_err_descr->get_field_err_values(ai);
- ed = p_err_descr->get_field_emb_descr (ai);
- }
- else { // not USE-ORDER, sequential access
- ev = p_err_descr->next_field_err_values(ai, values_idx);
- ed = p_err_descr->next_field_emb_descr (ai, edescr_idx);
- }
- ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr
-
- if (ai < p_err_descr->omit_before) continue;
-
- // omit_after value -1 becomes "very big".
- if ((unsigned int)ai > (unsigned int)p_err_descr->omit_after) continue;
- // We can't skip all fields with break, because the next ai may be lower
- // than omit_after.
-
- sub_len += ordered->encode_field(ai, ev, ed, p_buf,
- // Pass USE-NIL to the last field (except when USE-ORDER is also in effect,
- // because the tag-stripping effect of USE-NIL has been achieved
- // by encoding the sub-fields directly).
- flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0),
- indent + !omit_tag);
-
- // Now the next embed-values string (NOT affected by USE-ORDER!)
- int i1 = i - begin + 1;
- if (exer && (p_td.xer_bits & EMBED_VALUES) && i1 < expected_embed) {
- const Erroneous_values_t * ev0_i = NULL;
- const Erroneous_descriptor_t* ed0_i = NULL;
- if (ed0) {
- ev0_i = ed0->next_field_err_values(i1, embed_values_val_idx);
- ed0_i = ed0->next_field_emb_descr (i1, embed_values_descr_idx);
+ 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) {
+ emb_val = new embed_values_enc_struct_t;
+ emb_val->embval_array = embed_values;
+ emb_val->embval_index = 1;
+ emb_val->embval_err = ed0;
+ emb_val->embval_err_val_idx = embed_values_val_idx;
+ emb_val->embval_err_descr_idx = embed_values_descr_idx;
+ }
+
+ for ( i = begin; i < end; ++i ) {
+
+ const Base_Type *uoe = 0; // "useOrder enum"
+ const Enum_Type *enm = 0; // the enum value selecting the field
+
+ // "actual" index, may be perturbed by USE-ORDER.
+ // We use this value to index the appropriate record.
+ int ai = i;
+
+ const Erroneous_values_t * ev = NULL;
+ const Erroneous_descriptor_t* ed = NULL;
+ if (exer && use_order) {
+ // If USE-ORDER is in effect, it introduces a level of indirection
+ // into the indexing of fields: "i" is used to select an element
+ // of the use_order member (an enum), whose value is used to select
+ // the field being encoded.
+ uoe = use_order->get_at(i - begin);
+ enm = static_cast<const Enum_Type *>(uoe);
+ ai = enm->as_int() + useorder_base;
+
+ // Because it is not guaranteed that ai will increase monotonically,
+ // we can't use next_field_...().
+ ev = p_err_descr->get_field_err_values(ai);
+ ed = p_err_descr->get_field_emb_descr (ai);
+ }
+ else { // not USE-ORDER, sequential access
+ ev = p_err_descr->next_field_err_values(ai, values_idx);
+ ed = p_err_descr->next_field_emb_descr (ai, edescr_idx);
+ }
+ ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr
+
+ if (ai < p_err_descr->omit_before) continue;
+
+ // omit_after value -1 becomes "very big".
+ if ((unsigned int)ai > (unsigned int)p_err_descr->omit_after) continue;
+ // We can't skip all fields with break, because the next ai may be lower
+ // than omit_after.
+
+ sub_len += ordered->encode_field(ai, ev, ed, p_buf,
+ // Pass USE-NIL to the last field (except when USE-ORDER is also in effect,
+ // because the tag-stripping effect of USE-NIL has been achieved
+ // by encoding the sub-fields directly).
+ flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0),
+ indent + !omit_tag, emb_val);
+
+ // 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()) {
+ const Erroneous_values_t * ev0_i = NULL;
+ const Erroneous_descriptor_t* ed0_i = NULL;
+ if (ed0) {
+ ev0_i = ed0->next_field_err_values(emb_val->embval_index, emb_val->embval_err_val_idx);
+ ed0_i = ed0->next_field_emb_descr (emb_val->embval_index, emb_val->embval_err_descr_idx);
+ }
+ embed_values->encode_element(emb_val->embval_index, UNIVERSAL_CHARSTRING_xer_,
+ ev0_i, ed0_i, p_buf, flavor | EMBED_VALUES, indent + !omit_tag, 0);
+ ++emb_val->embval_index;
}
- embed_values->encode_element(i1, ev0_i, ed0_i,
- p_buf, flavor | EMBED_VALUES, indent + !omit_tag);
+ } //for
+ if (0 != emb_val) {
+ if (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)",
+ embed_values->size_of(), emb_val->embval_index);
+ }
+ delete emb_val;
}
- } //for
+ } // if (!early_to_bed)
} // if (QNAME)
return (int)p_buf.get_len() - encoded_length;
}
-int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor)
+int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
+ 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) {
if (xer_descr(k)->xer_bits & ANY_ATTRIBUTES) {
aa_index = k;
- static_cast<Record_Of_Type*>(get_at(aa_index))->set_size(0);
+ if (!get_at(aa_index)->is_optional()) {
+ static_cast<Record_Of_Type*>(get_at(aa_index))->set_size(0);
+ }
break; // there can be only one, 18.2.2
}
}
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);
+ 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);
+ 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
TTCN_EncDec_ErrorContext ec_2("Attribute %d: ", num_aa);
// We have a component with ANY-ATTRIBUTE. It must be a record of
// UNIVERSAL_CHARSTRING. Add the attribute to it.
- Record_Of_Type *aa = static_cast<Record_Of_Type *>(get_at(aa_index));
+ Record_Of_Type *aa = 0;
+ if (get_at(aa_index)->is_optional()) {
+ if (num_aa == 0) {
+ get_at(aa_index)->set_to_present();
+ }
+ aa = static_cast<Record_Of_Type*>(get_at(aa_index)->get_opt_value());
+ }
+ else {
+ aa = static_cast<Record_Of_Type*>(get_at(aa_index));
+ }
UNIVERSAL_CHARSTRING *new_elem = static_cast<UNIVERSAL_CHARSTRING *>
(aa->get_at(num_aa++));
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) * * * * * * * * * * * */
- Record_Of_Type* embed_values = 0;
+ embed_values_dec_struct_t* emb_val = 0;
+ bool emb_val_optional = false;
if (exer && (p_td.xer_bits & EMBED_VALUES)) {
- embed_values = static_cast<Record_Of_Type*>(get_at(0));
+ emb_val = new embed_values_dec_struct_t;
+ 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;
}
if (exer && (p_td.xer_bits & USE_ORDER)) {
get_at(oi)->set_to_omit();
++n_optionals;
}
+
Record_Of_Type *use_order = static_cast<Record_Of_Type*>(get_at(uo_index));
// Initialize the use_order field to empty. Let it grow on demand.
// (setting it to the minimum acceptable size may leave unbound elements
// if the XML was incomplete).
use_order->set_size(0);
- Record_Type *jumbled = this; // the record affected by USE_ORDER
- int begin = first_nonattr;
- int end = field_cnt; // "one past"
- if (p_td.xer_bits & USE_NIL) {
- Base_Type *last_optional = get_at(field_cnt-1);
- if (!usenil_attribute) { // exer known true
- last_optional->set_to_present();
- jumbled = static_cast<Record_Type*>(last_optional->get_opt_value());
- // We will operate on the members of last_optional,
- // effectively bypassing last_optional->XER_decode() itself.
- begin = 0;
- end = jumbled->get_count();
- ec_1.set_msg("%s': ", fld_name(field_cnt-1));
+ // Nothing to order if there are no child elements
+ if (!tag_closed) {
+ Record_Type *jumbled = this; // the record affected by USE_ORDER
+ int begin = first_nonattr;
+ int end = field_cnt; // "one past"
+ if (p_td.xer_bits & USE_NIL) {
+ Base_Type *last_optional = get_at(field_cnt-1);
+ if (!usenil_attribute) { // exer known true
+ last_optional->set_to_present();
+ jumbled = static_cast<Record_Type*>(last_optional->get_opt_value());
+ // We will operate on the members of last_optional,
+ // effectively bypassing last_optional->XER_decode() itself.
+ begin = 0;
+ end = jumbled->get_count();
+ ec_1.set_msg("%s': ", fld_name(field_cnt-1));
+ }
}
- }
- if (num_attributes > 0
- && first_nonattr != field_cnt
- && i == first_nonattr - 1) { // exer known true
- // If there were attributes and their processing just finished,
- // the reader is positioned on the start tag of the record.
- // Move ahead, unless there are no non-attribute fields.
- reader.Read();
- }
- // Then, the non-attributes
-
- // The index runs over the members affected by USE-ORDER.
- // This is [first_nonattr,field_cnt) unless USE-NIL is involved,
- // in which case it's [0,optional_sequence::field_cnt)
- int *seen = new int[end-begin];
- int num_seen = 0;
- int last_any_elem = begin - 1;
- for (i = begin; i < end; i++) {
- for (success = reader.Ok(); success == 1; success = reader.Read()) {
- type = reader.NodeType();
- if (embed_values) {
- if (reader.NodeType()==XML_READER_TYPE_TEXT) {
+ if (num_attributes > 0
+ && first_nonattr != field_cnt
+ && i == first_nonattr - 1) { // exer known true
+ // If there were attributes and their processing just finished,
+ // the reader is positioned on the start tag of the record.
+ // Move ahead, unless there are no non-attribute fields.
+ reader.Read();
+ }
+ // Then, the non-attributes
+
+ // The index runs over the members affected by USE-ORDER.
+ // This is [first_nonattr,field_cnt) unless USE-NIL is involved,
+ // in which case it's [0,optional_sequence::field_cnt)
+ int *seen = new int[end-begin];
+ int num_seen = 0;
+ int last_any_elem = begin - 1;
+ // The index of the latest embedded value can change outside of this function
+ // (if the field is an untagged record of), in this case the next value should
+ // be ignored, as it's already been handled by the record of
+ int last_embval_index = 0;
+ bool early_exit = false;
+ for (i = begin; i < end; i++) {
+ for (success = reader.Ok(); success == 1; success = reader.Read()) {
+ type = reader.NodeType();
+ if (0 != emb_val && reader.NodeType()==XML_READER_TYPE_TEXT) {
UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
- embed_values->get_at(i-begin)->set_value(&emb_ustr);
+ emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+ }
+ // The non-attribute components must not be UNTAGGED
+ if (type == XML_READER_TYPE_ELEMENT) break;
+ if (type == XML_READER_TYPE_END_ELEMENT) {
+ early_exit = true;
+ break;
}
}
- // The non-attribute components must not be UNTAGGED
- if (type == XML_READER_TYPE_ELEMENT) break;
- // else if (type==XML_READER_TYPE_END_ELEMENT) panic?
- }
- if (success != 1) break;
- const char *name = (const char *)reader.LocalName();
- boolean field_name_found = false;
- // Find out which member it is.
- // FIXME some hashing should be implemented
- for (int k = begin; k < end; k++) {
- if (!(jumbled->xer_descr(k)->xer_bits & ANY_ELEMENT) &&
- check_name(name, *jumbled->xer_descr(k), 1)) {
- ec_1.set_msg("%s': ", jumbled->fld_name(k));
-
- // Check for the same field being decoded twice.
- // We can't use the field's is_bound()/is_present(),
- // because the field may be bound on input, e.g. for
- // prototype(fast) or prototype(backtrack).
- int in_dex = k - begin;
- for (int o = 0; o < num_seen ;++o) {
- if (in_dex == seen[o]) TTCN_EncDec_ErrorContext::error(
- TTCN_EncDec::ET_INVAL_MSG, "Duplicate element");
+ if (0 != emb_val) {
+ if (last_embval_index == emb_val->embval_index) {
+ ++emb_val->embval_index;
}
- seen[num_seen++] = in_dex;
- // Set the next use-order member.
- // Non-const get_at creates the object in the record-of.
- 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);
- field_name_found = true;
- break;
+ last_embval_index = emb_val->embval_index;
}
- }
- if (!field_name_found) {
- // Check the anyElement fields
- for (int k = last_any_elem + 1; k < end; k++) {
- if (jumbled->xer_descr(k)->xer_bits & ANY_ELEMENT) {
+ if (success != 1 || early_exit) break;
+ const char *name = (const char *)reader.LocalName();
+ bool field_name_found = false;
+ // Find out which member it is.
+ // FIXME some hashing should be implemented
+ for (int k = begin; k < end; k++) {
+ if (!(jumbled->xer_descr(k)->xer_bits & ANY_ELEMENT) &&
+ check_name(name, *jumbled->xer_descr(k), 1)) {
ec_1.set_msg("%s': ", jumbled->fld_name(k));
// Check for the same field being decoded twice.
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);
- last_any_elem = k;
+ b->XER_decode(*jumbled->xer_descr(k), reader, flavor, flavor2, emb_val);
+ field_name_found = true;
break;
}
}
+ if (!field_name_found) {
+ // Check the anyElement fields
+ for (int k = last_any_elem + 1; k < end; k++) {
+ if (jumbled->xer_descr(k)->xer_bits & ANY_ELEMENT) {
+ ec_1.set_msg("%s': ", jumbled->fld_name(k));
+
+ // Check for the same field being decoded twice.
+ // We can't use the field's is_bound()/is_present(),
+ // because the field may be bound on input, e.g. for
+ // prototype(fast) or prototype(backtrack).
+ int in_dex = k - begin;
+ for (int o = 0; o < num_seen ;++o) {
+ if (in_dex == seen[o]) TTCN_EncDec_ErrorContext::error(
+ TTCN_EncDec::ET_INVAL_MSG, "Duplicate element");
+ }
+ seen[num_seen++] = in_dex;
+ // Set the next use-order member.
+ // Non-const get_at creates the object in the record-of.
+ 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, flavor2, emb_val);
+ last_any_elem = k;
+ field_name_found = true;
+ break;
+ }
+ }
+ }
+ if (!field_name_found) {
+ TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
+ "Bad XML tag '%s' instead of a valid field", name);
+ break;
+ }
+ } // next field
+ if (0 != emb_val) {
+ if (reader.NodeType()==XML_READER_TYPE_TEXT) {
+ UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
+ emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+ }
+ if (last_embval_index == emb_val->embval_index) {
+ ++emb_val->embval_index;
+ }
}
- } // next field
- if (embed_values) {
- if (reader.NodeType()==XML_READER_TYPE_TEXT) {
- UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
- embed_values->get_at(i-begin)->set_value(&emb_ustr);
- }
- }
- delete [] seen;
- ec_1.set_msg(" "); // no active component
- ec_0.set_msg(" ");
-
- // Check that we collected the required number of children
- int num_collected = use_order->size_of();
- if (p_td.xer_bits & USE_NIL) {
- int expected = usenil_attribute ? 0 : jumbled->get_count();
- if (num_collected != expected) {
- TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
- "Incorrect number of fields %d, expected %d",
- num_collected, expected);
+ delete [] seen;
+ ec_1.set_msg(" "); // no active component
+ ec_0.set_msg(" ");
+
+ // Check that we collected the required number of children
+ int num_collected = use_order->size_of();
+ if (p_td.xer_bits & USE_NIL) {
+ int expected = usenil_attribute ? 0 : jumbled->get_count();
+ if (num_collected != expected) {
+ TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
+ "Incorrect number of fields %d, expected %d",
+ num_collected, expected);
+ }
}
- }
- else {
- if (num_collected < field_cnt - first_nonattr - n_optionals
- ||num_collected > field_cnt - first_nonattr) {
- TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
- "Wrong number of fields! size = %d, expected %d..%d",
- use_order->size_of(), field_cnt - first_nonattr - n_optionals,
- field_cnt - first_nonattr);
+ else {
+ if (num_collected < field_cnt - first_nonattr - n_optionals
+ ||num_collected > field_cnt - first_nonattr) {
+ TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
+ "Wrong number of fields! size = %d, expected %d..%d",
+ use_order->size_of(), field_cnt - first_nonattr - n_optionals,
+ field_cnt - first_nonattr);
+ }
}
- }
+ } // not empty element
}
else { // not USE-ORDER, simpler code
if (usenil_attribute) {
reader.MoveToElement(); // value absent, nothing more to do
} else {
- int emb_idx = 0;
+ // The index of the latest embedded value can change outside of this function
+ // (if the field is a untagged record of), in this case the next value should
+ // be ignored, as it's already been handled by the record of
+ // Omitted fields can also reset this value
+ int last_embval_index = 0;
for (; i<field_cnt; i++) {
- if (embed_values) {
+ if (0 != emb_val) {
if (reader.NodeType()==XML_READER_TYPE_TEXT) {
UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
- embed_values->get_at(emb_idx)->set_value(&emb_ustr);
+ emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+ }
+ if (last_embval_index == emb_val->embval_index) {
+ ++emb_val->embval_index;
}
- emb_idx++;
+ last_embval_index = emb_val->embval_index;
}
ec_1.set_msg("%s': ", fld_name(i));
if (exer && i==field_cnt-1 && p_td.dfeValue && reader.IsEmptyElement()) {
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);
+ get_at(i)->XER_decode(*xer_descr(i), reader, new_flavor, flavor2, emb_val);
}
}
+ if (!get_at(i)->is_present()) {
+ // there was no new element, the last embedded value is for the next field
+ // (or the end of the record if this is the last field)
+ last_embval_index = -1;
+ }
} // next field
- if (embed_values) {
+ if (0 != emb_val) {
if (reader.NodeType()==XML_READER_TYPE_TEXT) {
UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
- embed_values->get_at(emb_idx)->set_value(&emb_ustr);
+ emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+ }
+ if (last_embval_index == emb_val->embval_index) {
+ ++emb_val->embval_index;
}
}
}
} // if use-order
- if (embed_values) {
- // Set the embed_values member to the correct number of strings
- int num_embedded = 0; // if usenil_attribute
- if (!usenil_attribute) {
- num_embedded = field_cnt - first_nonattr + 1;
- const int num_opt = optional_count();
- const int * optionals = get_optional_indexes();
- for (int opt_idx = 0; opt_idx < num_opt; ++opt_idx) {
- // skip optional attributes
- if (optionals[opt_idx] < start_at + num_attributes) continue;
- // reduce for each omitted member
- if (!get_at(optionals[opt_idx])->is_present()) --num_embedded;
+ 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;
}
}
- embed_values->set_size(num_embedded);
- static const UNIVERSAL_CHARSTRING emptystring(0, (const char*)NULL);
- for (int j = 0; j < num_embedded; ++j) {
- if (!embed_values->get_at(j)->is_bound()) embed_values->get_at(j)->set_value(&emptystring);
+ 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
} // if use-qname
-
+
+ // Check if every non-optional field has been set
+ for (i = 0; i < field_cnt; ++i) {
+ if (!get_at(i)->is_optional() && !get_at(i)->is_bound()) {
+ TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
+ "No data found for non-optional field '%s'", fld_name(i));
+ }
+ }
+
if (own_tag) {
// We had our start tag. Then our fields did their thing.
// Now we expect the end tag. And it better be our end tag!
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_optional() || get_at(i)->is_present()) {
- if (NULL != fld_descr(i)->json && NULL != fld_descr(i)->json->alias) {
- enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, fld_descr(i)->json->alias);
+ get_at(i)->is_present() || metainfo_unbound) {
+ const char* field_name = (NULL != fld_descr(i)->json && NULL != fld_descr(i)->json->alias) ?
+ fld_descr(i)->json->alias : fld_name(i);
+ 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 {
+ enc_len += get_at(i)->JSON_encode(*fld_descr(i), p_tok);
+ }
+ }
+ }
+
+ enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+ 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 {
- enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, fld_name(i));
+ 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);
}
- enc_len += get_at(i)->JSON_encode(*fld_descr(i), p_tok);
+ }
+
+ if (-1 != p_err_descr->omit_after && p_err_descr->omit_after <= i) {
+ break;
}
}
}
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;
+ }
+
while (true) {
// Read name - value token pairs until we reach some other token
char* name = 0;
break;
}
else {
+ // check for meta info
+ boolean is_metainfo = FALSE;
+ if (name_len > 9 && 0 == strncmp(name, "metainfo ", 9)) {
+ name += 9;
+ name_len -= 9;
+ is_metainfo = TRUE;
+ }
+
// check field name
int field_idx;
for (field_idx = 0; field_idx < field_count; ++field_idx) {
}
if (strlen(expected_name) == name_len &&
0 == strncmp(expected_name, name, name_len)) {
+ field_found[field_idx] = TRUE;
break;
}
}
if (field_count == field_idx) {
// invalid field name
char* name2 = mcopystrn(name, name_len);
- JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, name2);
+ JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, is_metainfo ?
+ JSON_DEC_METAINFO_NAME_ERROR : JSON_DEC_INVALID_NAME_ERROR, name2);
// if this is set to a warning, skip the value of the field
dec_len += p_tok.get_next_token(&token, NULL, NULL);
if (JSON_TOKEN_NUMBER != token && JSON_TOKEN_STRING != token &&
continue;
}
- int ret_val = get_at(field_idx)->JSON_decode(*fld_descr(field_idx), p_tok, p_silent);
- if (0 > ret_val) {
- if (JSON_ERROR_INVALID_TOKEN) {
- JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name(field_idx));
+ if (is_metainfo) {
+ if (JSON_METAINFO_NOT_APPLICABLE != metainfo[field_idx]) {
+ // check meta info
+ char* info_value = 0;
+ size_t info_len = 0;
+ dec_len += p_tok.get_next_token(&token, &info_value, &info_len);
+ if (JSON_TOKEN_STRING == token && 9 == info_len &&
+ 0 == strncmp(info_value, "\"unbound\"", 9)) {
+ metainfo[field_idx] = JSON_METAINFO_UNBOUND;
+ }
+ else {
+ JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_VALUE_ERROR,
+ fld_name(field_idx));
+ return JSON_ERROR_FATAL;
+ }
}
- return JSON_ERROR_FATAL;
+ else {
+ JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_NOT_APPLICABLE,
+ fld_name(field_idx));
+ return JSON_ERROR_FATAL;
+ }
+ }
+ else {
+ buf_pos = p_tok.get_buf_pos();
+ int ret_val = get_at(field_idx)->JSON_decode(*fld_descr(field_idx), p_tok, p_silent);
+ if (0 > ret_val) {
+ if (JSON_ERROR_INVALID_TOKEN == ret_val) {
+ // undo the last action on the buffer, check if the invalid token was a null token
+ p_tok.set_buf_pos(buf_pos);
+ p_tok.get_next_token(&token, NULL, NULL);
+ if (JSON_TOKEN_LITERAL_NULL == token) {
+ if (JSON_METAINFO_NONE == metainfo[field_idx]) {
+ // delay reporting an error for now, there might be meta info later
+ metainfo[field_idx] = JSON_METAINFO_NEEDED;
+ continue;
+ }
+ else if (JSON_METAINFO_UNBOUND == metainfo[field_idx]) {
+ // meta info already found
+ continue;
+ }
+ }
+ JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name(field_idx));
+ }
+ return JSON_ERROR_FATAL;
+ }
+ dec_len += ret_val;
}
- dec_len += ret_val;
}
}
return JSON_ERROR_FATAL;
}
- // Check if every field has been set
+ // Check if every field has been set and handle meta info
for (int field_idx = 0; field_idx < field_count; ++field_idx) {
Base_Type* field = get_at(field_idx);
- if (!field->is_bound()) {
+ if (JSON_METAINFO_UNBOUND == metainfo[field_idx]) {
+ field->clean_up();
+ }
+ else if (JSON_METAINFO_NEEDED == metainfo[field_idx]) {
+ // 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_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;
+
return dec_len;
}
void Empty_Record_Type::set_param(Module_Param& param) {
param.basic_check(Module_Param::BC_VALUE, "empty record/set value (i.e. { })");
- if (param.get_type()!=Module_Param::MP_Value_List || param.get_size()>0) {
+ Module_Param_Ptr mp = ¶m;
+ if (param.get_type() == Module_Param::MP_Reference) {
+ mp = param.get_referenced_param();
+ }
+ if (mp->get_type()!=Module_Param::MP_Value_List || mp->get_size()>0) {
param.type_error("empty record/set value (i.e. { })", get_descriptor()->name);
}
bound_flag = TRUE;
}
+Module_Param* Empty_Record_Type::get_param(Module_Param_Name& /* param_name */) const
+{
+ if (!is_bound()) {
+ return new Module_Param_Unbound();
+ }
+ return new Module_Param_Value_List();
+}
+
void Empty_Record_Type::encode_text(Text_Buf& /*text_buf*/) const
{
if (!bound_flag)
case TTCN_EncDec::CT_XER: {
TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
unsigned XER_coding=va_arg(pvar, unsigned);
- XER_encode(*(p_td.xer),p_buf, XER_coding, 0);
+ XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0);
p_buf.put_c('\n');
break;}
case TTCN_EncDec::CT_JSON: {
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);
+ 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_encode(const XERdescriptor_t& p_td,
- TTCN_Buffer& p_buf, unsigned int flavor, int indent) const
+ TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
{
int encoded_length=(int)p_buf.get_len();
int indenting = !is_canonical(flavor);
}
int Empty_Record_Type::XER_decode(const XERdescriptor_t& p_td,
- XmlReaderWrap& reader, unsigned int flavor)
+ XmlReaderWrap& reader, unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*)
{
int exer = is_exer(flavor);
bound_flag = true;