Commit 3f84031e authored by Elemer Lelik's avatar Elemer Lelik
Browse files

Sync with 5.4.2

parent 51fa56b9
!Makefile
\ No newline at end of file
# Makefile for pseudoinstall
TOP := ..
include $(TOP)/Makefile.cfg
all run:
$(ABS_SRC)/../pseudoinstall
# Should this delete ?
clean distclean: ;
# definitely do-nothing
dep install: ;
# All targets are phony
.PHONY: all run clean distclean dep install
export OPENSSL_DIR XMLDIR
......@@ -379,6 +379,11 @@ int JSON_Tokenizer::put_next_token(json_token_t p_token, const char* p_token_str
return buf_len - start_len;
}
void JSON_Tokenizer::put_raw_data(const char* p_data, size_t p_len)
{
buf_ptr = mputstrn(buf_ptr, p_data, p_len);
buf_len += p_len;
}
char* convert_to_json_string(const char* str)
{
......
......@@ -158,6 +158,11 @@ public:
* @return The number of characters added to the JSON document */
int put_next_token(json_token_t p_token, const char* p_token_str = 0);
/** Adds raw data to the end of the buffer.
* @param p_data [in] Pointer to the beginning of the data
* @param p_len [in] Length of the data in bytes */
void put_raw_data(const char* p_data, size_t p_len);
}; // class JSON_Tokenizer
// A dummy JSON tokenizer, use when there is no actual JSON document
......
......@@ -11,7 +11,7 @@
/* Version numbers */
#define TTCN3_MAJOR 5
#define TTCN3_MINOR 4
#define TTCN3_PATCHLEVEL 1
#define TTCN3_PATCHLEVEL 2
//#define TTCN3_BUILDNUMBER 0
/* The aggregated version number must be set manually since some stupid
......@@ -22,7 +22,7 @@
* TTCN3_VERSION = TTCN3_MAJOR * 1000000 + TTCN3_MINOR * 10000 +
* TTCN3_PATCHLEVEL * 100 + TTCN3_BUILDNUMBER
*/
#define TTCN3_VERSION 50401
#define TTCN3_VERSION 50402
/* A monotonically increasing version number.
* An official release is deemed to have the highest possible build number (99)
......
......@@ -32,6 +32,8 @@ namespace Common {
// =================================
// ===== Modules
// =================================
vector<Modules::type_enc_t> Modules::delayed_type_enc_v;
Modules::Modules()
: Node(), mods_v(), mods_m()
......@@ -150,6 +152,14 @@ namespace Common {
mods_v[i]->chk_recursive(checked_modules);
}
checked_modules.clear();
// run delayed Type::chk_coding() calls
if (!delayed_type_enc_v.empty()) {
for (size_t i = 0; i < delayed_type_enc_v.size(); ++i) {
delayed_type_enc_v[i]->t->chk_coding(delayed_type_enc_v[i]->enc, true);
delete delayed_type_enc_v[i];
}
delayed_type_enc_v.clear();
}
}
void Modules::chk_top_level_pdus()
......@@ -270,6 +280,14 @@ namespace Common {
mods_v[i]->generate_json_schema(json, json_refs);
}
}
void Modules::delay_type_encode_check(Type* p_type, bool p_encode)
{
type_enc_t* elem = new type_enc_t;
elem->t = p_type;
elem->enc = p_encode;
delayed_type_enc_v.add(elem);
}
// =================================
......
......@@ -77,6 +77,13 @@ namespace Common {
/** Containers to store the modules. */
vector<Module> mods_v;
map<string, Module> mods_m;
/** Contains info needed for delayed type encoding checks */
struct type_enc_t {
Type* t;
bool enc;
};
static vector<type_enc_t> delayed_type_enc_v;
/** Not implemented */
Modules(const Modules& p);
......@@ -125,6 +132,13 @@ namespace Common {
* @param json_refs map of JSON documents containing the references and function
* info related to each type */
void generate_json_schema(JSON_Tokenizer& json, map<Type*, JSON_Tokenizer>& json_refs);
/** Called if a Type::chk_coding() call could not be resolved (because the
* needed custom coding function was not found yet, but it might be among
* the functions that have not been checked yet).
* This stores the info needed to call the function again after everything
* else has been checked. */
static void delay_type_encode_check(Type* p_type, bool p_encode);
};
/**
......
This diff is collapsed.
......@@ -180,7 +180,8 @@ namespace Common {
CT_RAW, /**< TTCN-3 RAW */
CT_TEXT, /**< TTCN-3 TEXT */
CT_XER, /**< ASN.1 XER */
CT_JSON /**< TTCN-3 JSON */
CT_JSON, /**< TTCN-3 JSON */
CT_CUSTOM /**< user defined encoding */
};
/** selector for value checking algorithms */
......@@ -548,10 +549,13 @@ namespace Common {
* \p p_right_chain are there to prevent infinite recursion.
* \p p_left_chain contains the type chain of the left operand from the
* "root" type to this point in the type's structure. \p p_right_chain
* is the same for the right operand. */
* is the same for the right operand.
* \p p_is_inline_template indicates that the conversion is requested for an
* inline template. Type conversion code is not needed in this case. */
bool is_compatible(Type *p_type, TypeCompatInfo *p_info,
TypeChain *p_left_chain = NULL,
TypeChain *p_right_chain = NULL);
TypeChain *p_right_chain = NULL,
bool p_is_inline_template = false);
/** Check if the restrictions of a T_SEQOF/T_SETOF are "compatible" with
* the given type \a p_type. Can be called only as a T_SEQOF/T_SETOF.
* Currently, used for structured types only. \a p_type can be any kind
......@@ -572,25 +576,33 @@ namespace Common {
* \p p_right_chain are there to prevent infinite recursion.
* \p p_left_chain contains the type chain of the left operand from the
* "root" type to this point in the type's structure. \p p_right_chain
* is the same for the right operand. */
* is the same for the right operand.
* \p p_is_inline_template indicates that the conversion is requested for an
* inline template. Type conversion code is not needed in this case. */
bool is_compatible_record(Type *p_type, TypeCompatInfo *p_info,
TypeChain *p_left_chain = NULL,
TypeChain *p_right_chain = NULL);
TypeChain *p_right_chain = NULL,
bool p_is_inline_template = false);
bool is_compatible_record_of(Type *p_type, TypeCompatInfo *p_info,
TypeChain *p_left_chain = NULL,
TypeChain *p_right_chain = NULL);
TypeChain *p_right_chain = NULL,
bool p_is_inline_template = false);
bool is_compatible_set(Type *p_type, TypeCompatInfo *p_info,
TypeChain *p_left_chain = NULL,
TypeChain *p_right_chain = NULL);
TypeChain *p_right_chain = NULL,
bool p_is_inline_template = false);
bool is_compatible_set_of(Type *p_type, TypeCompatInfo *p_info,
TypeChain *p_left_chain = NULL,
TypeChain *p_right_chain = NULL);
TypeChain *p_right_chain = NULL,
bool p_is_inline_template = false);
bool is_compatible_array(Type *p_type, TypeCompatInfo *p_info,
TypeChain *p_left_chain = NULL,
TypeChain *p_right_chain = NULL);
TypeChain *p_right_chain = NULL,
bool p_is_inline_template = false);
bool is_compatible_choice_anytype(Type *p_type, TypeCompatInfo *p_info,
TypeChain *p_left_chain = NULL,
TypeChain *p_right_chain = NULL);
TypeChain *p_right_chain = NULL,
bool p_is_inline_template = false);
public:
/** Returns whether this type is identical to \a p_type from TTCN-3 point
* of view. Note: This relation is symmetric. The function returns true
......@@ -607,7 +619,10 @@ namespace Common {
/** Returns true if this is a list type (string, rec.of, set.of or array */
bool is_list_type(bool allow_array);
void chk_coding(bool encode);
/** Sets the encoding or decoding function for the type (in case of custom
* encoding). */
void set_coding_function(bool encode, const string& function_name);
void chk_coding(bool encode, bool delayed = false);
bool is_coding_by_function() const;
const string& get_coding(bool encode) const;
private:
......@@ -961,13 +976,13 @@ namespace Common {
bool hasVariantAttrs();
/** Returns whether the type has the encoding attribute specified by
* the parameter (either in its own 'with' statement or in the module's) */
bool hasEncodeAttr(const MessageEncodingType_t encoding_type);
bool hasEncodeAttr(const char* encoding_name);
/** Returns whether \a this can be encoded according to rules
* \a p_encoding.
* @note Should be called only during code generation, after the entire
* AST has been checked, or else the compiler might choke on code like:
* type MyRecordOfType[-] ElementTypeAlias; */
bool has_encoding(const MessageEncodingType_t encoding_type);
bool has_encoding(const MessageEncodingType_t encoding_type, const string* custom_encoding = NULL);
/** Generates the C++ equivalent class(es) of the type. */
void generate_code(output_struct *target);
size_t get_codegen_index(size_t index);
......@@ -1171,6 +1186,10 @@ namespace Common {
void generate_json_schema_ref(JSON_Tokenizer& json);
JsonAST* get_json_attributes() const { return jsonattrib; }
/** Returns true if the type is a union with the JSON "as value" attribute, or
* if a union with this attribute is embedded in the type. */
bool has_as_value_union();
};
/** @} end of AST_Type group */
......
......@@ -113,7 +113,7 @@ void Type::chk()
textattrib = new TextAST;
if(!xerattrib && hasVariantAttrs() && hasNeedofXerAttrs())
xerattrib = new XerAttributes;
if (!jsonattrib && (hasVariantAttrs() || hasEncodeAttr(CT_JSON) || hasNeedofJsonAttrs())) {
if (!jsonattrib && (hasVariantAttrs() || hasEncodeAttr(get_encoding_name(CT_JSON)) || hasNeedofJsonAttrs())) {
jsonattrib = new JsonAST;
}
break;
......@@ -1034,7 +1034,7 @@ void Type::chk_xer_embed_values(int num_attributes)
{
Type * const last = get_type_refd_last();
enum complaint_type { ALL_GOOD, OPTIONAL_OR_DEFAULT, UNTAGGED_EMBEDVAL,
enum complaint_type { ALL_GOOD, HAVE_DEFAULT, UNTAGGED_EMBEDVAL,
NOT_SEQUENCE, EMPTY_SEQUENCE, FIRST_NOT_SEQOF, SEQOF_NOT_STRING,
SEQOF_BAD_LENGTH, UNTAGGED_OTHER } ;
complaint_type complaint = ALL_GOOD;
......@@ -1050,9 +1050,9 @@ void Type::chk_xer_embed_values(int num_attributes)
}
CompField *cf0 = last->get_comp_byIndex(0);
cf0t = cf0->get_type()->get_type_refd_last();
if (cf0->get_is_optional() || cf0->has_default()) {
complaint = OPTIONAL_OR_DEFAULT;
break; // 25.2.1 first component cannot be optional or have default
if (cf0->has_default()) {
complaint = HAVE_DEFAULT;
break; // 25.2.1 first component cannot have default
}
switch (cf0t->get_typetype()) { // check the first component
......@@ -1119,10 +1119,10 @@ void Type::chk_xer_embed_values(int num_attributes)
case EMPTY_SEQUENCE:
case FIRST_NOT_SEQOF:
case SEQOF_NOT_STRING:
case OPTIONAL_OR_DEFAULT:
case HAVE_DEFAULT:
error("A type with EMBED-VALUES must be a sequence type. "
"The first component of the sequence shall be SEQUENCE OF UTF8String "
"and shall not be marked OPTIONAL or DEFAULT");
"and shall not be marked DEFAULT");
break;
case SEQOF_BAD_LENGTH:
cf0t->error("Wrong length of SEQUENCE-OF for EMBED-VALUES, should be %lu",
......@@ -1139,7 +1139,6 @@ void Type::chk_xer_embed_values(int num_attributes)
} // switch(complaint)
} // if complaint and embedValues
}
/** Wraps a C string but compares by contents, not by pointer */
class stringval {
const char * str;
......@@ -1559,11 +1558,14 @@ void Type::chk_xer_use_nil()
enum complaint_type { ALL_GOOD, NO_CONTROLNS, NOT_SEQUENCE, EMPTY_SEQUENCE,
UNTAGGED_USENIL, COMPONENT_NOT_ATTRIBUTE, LAST_IS_ATTRIBUTE,
LAST_NOT_OPTIONAL, INCOMPATIBLE, WRONG_OPTIONAL_TYPE, EMBED_CHARENC };
LAST_NOT_OPTIONAL, INCOMPATIBLE, WRONG_OPTIONAL_TYPE, EMBED_CHARENC,
NOT_COMPATIBLE_WITH_USEORDER, BAD_ENUM, FIRST_OPTIONAL, NOTHING_TO_ORDER,
FIRST_NOT_RECORD_OF_ENUM, ENUM_GAP };
complaint_type complaint = ALL_GOOD;
CompField *cf = 0;
CompField *cf_last = 0;
const char *ns, *prefix;
Type *the_enum = 0;
my_scope->get_scope_mod()->get_controlns(ns, prefix);
if (!prefix) complaint = NO_CONTROLNS; // don't bother checking further
......@@ -1605,6 +1607,57 @@ void Type::chk_xer_use_nil()
if (!cf_last->get_is_optional()) {
complaint = LAST_NOT_OPTIONAL;
}
if(xerattrib->useOrder_ && cft->get_type_refd_last()->get_typetype() != T_SEQ_A
&& cft->get_type_refd_last()->get_typetype() != T_SEQ_T){
complaint = NOT_COMPATIBLE_WITH_USEORDER;
}else if(xerattrib->useOrder_) {
//This check needed, because if the record that has useOrder only
//has one field that is a sequence type, then the useNilPossible
//would be always true, that would lead to incorrect code generation.
Type * inner = cft->get_type_refd_last();
size_t useorder_index = xerattrib->embedValues_;
CompField *uo_field = last->get_comp_byIndex(useorder_index);
Type *uot = uo_field->get_type();
if (uot->get_type_refd_last()->typetype == T_SEQOF) {
the_enum = uot->get_ofType()->get_type_refd_last();
if(the_enum->typetype != T_ENUM_A && the_enum->typetype != T_ENUM_T){
complaint = FIRST_NOT_RECORD_OF_ENUM;
break;
}else if (uo_field->get_is_optional() || uo_field->get_defval() != 0) {
complaint = FIRST_OPTIONAL;
break;
}
size_t expected_enum_items = inner->get_nof_comps();
size_t enum_index = 0;
if (expected_enum_items == 0)
complaint = NOTHING_TO_ORDER;
else if (the_enum->u.enums.eis->get_nof_eis() != expected_enum_items)
complaint = BAD_ENUM;
else for (size_t i = 0; i < expected_enum_items; ++i) {
CompField *inner_cf = inner->get_comp_byIndex(i);
Type *inner_cft = inner_cf->get_type();
if (inner_cft->xerattrib && inner_cft->xerattrib->attribute_) continue;
// Found a non-attribute component. Its name must match an enumval
const Identifier& field_name = inner_cf->get_name();
const EnumItem *ei = the_enum->get_ei_byIndex(enum_index);
const Identifier& enum_name = ei->get_name();
if (field_name != enum_name) {// X.693amd1 35.2.2.1 and 35.2.2.2
complaint = BAD_ENUM;
break;
}
Value *v = ei->get_value();
const int_val_t *ival = v->get_val_Int();
const Int enumval = ival->get_val();
if ((size_t)enumval != enum_index) {
complaint = ENUM_GAP; // 35.2.2.3
break;
}
++enum_index;
}
}
}
if (cft->xerattrib) {
if ( cft->xerattrib->attribute_
......@@ -1615,9 +1668,10 @@ void Type::chk_xer_use_nil()
if (has_ae(cft->xerattrib)
||has_aa(cft->xerattrib)
||cft->xerattrib->defaultForEmpty_ != 0
||cft->xerattrib->embedValues_ ||cft->xerattrib->untagged_
||cft->xerattrib->useNil_ ||cft->xerattrib->useOrder_
||cft->xerattrib->defaultForEmpty_ != 0
||cft->xerattrib->untagged_
||cft->xerattrib->useNil_
||cft->xerattrib->useOrder_
||cft->xerattrib->useType_) { // or PI-OR-COMMENT
complaint = INCOMPATIBLE; // 33.2.3
}
......@@ -1683,7 +1737,7 @@ void Type::chk_xer_use_nil()
case INCOMPATIBLE:
cf_last->error("The OPTIONAL component of USE-NIL cannot have any of the "
"following encoding instructions: ANY-ATTRIBUTES, ANY-ELEMENT, "
"DEFAULT-FOR-EMPTY, EMBED-VALUES, PI-OR-COMMENT, UNTAGGED, "
"DEFAULT-FOR-EMPTY, PI-OR-COMMENT, UNTAGGED, "
"USE-NIL, USE-ORDER, USE-TYPE.");
break;
case WRONG_OPTIONAL_TYPE:
......@@ -1696,6 +1750,33 @@ void Type::chk_xer_use_nil()
"the optional component supporting USE-NIL shall not be "
"a character-encodable type.");
break;
case NOT_COMPATIBLE_WITH_USEORDER:
cf_last->error("The OTIONAL component of USE-NIL must be "
"a SEQUENCE/record when USE-ORDER is set for the parent type.");
break;
case BAD_ENUM:
if (!the_enum) FATAL_ERROR("Type::chk_xer_use_order()");
the_enum->error("Enumeration items should match the"
" non-attribute components of the field %s",
cf_last->get_name().get_dispname().c_str());
break;
case FIRST_OPTIONAL:
error("The record-of for USE-ORDER shall not be marked"
" OPTIONAL or DEFAULT"); // X.693amd1 35.2.3
break;
case NOTHING_TO_ORDER:
error("The component (%s) should have at least one non-attribute"
" component if USE-ORDER is present",
cf_last->get_name().get_dispname().c_str());
break;
case FIRST_NOT_RECORD_OF_ENUM:
error("The type with USE-ORDER should have a component "
"which is a record-of enumerated");
break;
case ENUM_GAP:
if (!the_enum) FATAL_ERROR("Type::chk_xer_use_order()");
the_enum->error("Enumeration values must start at 0 and have no gaps");
break;
} // switch
} // if USE-NIL
}
......@@ -1740,7 +1821,7 @@ void Type::chk_xer_use_order(int num_attributes)
if (xerattrib->useNil_) { // useNil in addition to useOrder
// This is an additional complication because USE-ORDER
// will affect the optional component, rather than the type itself
CompField *cf = get_comp_byIndex(ncomps-1);
CompField *cf = last->get_comp_byIndex(ncomps-1);
sequence_type = cf->get_type()->get_type_refd_last();
if (sequence_type->typetype == T_SEQ_T
||sequence_type->typetype == T_SEQ_A) {
......
......@@ -2081,7 +2081,8 @@ void Type::generate_code_Fat(output_struct *target)
}
fdef.runs_on_self = u.fatref.runs_on.self ? TRUE : FALSE;
fdef.is_startable = u.fatref.is_startable;
fdef.formal_par_list = u.fatref.fp_list->generate_code(memptystr());
fdef.formal_par_list = u.fatref.fp_list->generate_code(memptystr(),
u.fatref.fp_list->get_nof_fps());
u.fatref.fp_list->generate_code_defval(target);
fdef.actual_par_list = u.fatref.fp_list
->generate_code_actual_parlist(memptystr(),"");
......
......@@ -31,6 +31,7 @@
#include "ttcn3/Attributes.hh"
#include "../common/JSON_Tokenizer.hh"
#include "ttcn3/Ttcn2Json.hh"
#include <math.h>
#include <regex.h>
......@@ -9786,8 +9787,8 @@ error:
case Ttcn::Template::TEMPLATE_INVOKE:
break; // assume self-ref can't happen
case Ttcn::Template::TEMPLATE_ERROR:
FATAL_ERROR("Value::chk_expr_self_ref_templ()");
break; // not reached
//FATAL_ERROR("Value::chk_expr_self_ref_templ()");
break;
// default:
// FATAL_ERROR("todo ttype %d", t->get_templatetype());
// break; // and hope for the best
......@@ -12306,8 +12307,9 @@ error:
if (expr2.postamble)
expr->postamble = mputstr(expr->postamble, expr2.postamble);
} else
expr->expr = mputprintf(expr->expr, "%s(%s)",
gov_last->get_coding(true).c_str(), expr2.expr);
expr->expr = mputprintf(expr->expr, "%s(%s%s)",
gov_last->get_coding(true).c_str(), expr2.expr,
is_templ ? ".valueof()" : "");
Code::free_expr(&expr2);
}
......@@ -12626,49 +12628,10 @@ error:
return str;
}
/** This type contains the JSON encoding type of an omitted optional field */
enum omitted_json_value_t {
NOT_OMITTED, // the field is not omitted
OMITTED_ABSENT, // the omitted field is not present in the JSON object
OMITTED_NULL // the omitted field is set to 'null' in the JSON object
};
/** JSON code for omitted optional fields of can be generated in 2 ways:
* - the field is not present in the JSON object or
* - the field is present and its value is 'null'.
* Because of this all record/set values containing omitted fields have 2^N
* possible JSON encodings, where N is the number of omitted fields.
*
* This function helps go through all the possible encodings, by generating
* the next combination from a previous one.
*
* The algorithm is basically adding 1 to a binary number (where OMITTED_ABSENT
* is zero, OMITTED_NULL is one, all NOT_OMITTEDs are ignored and the first bit
* is the least significant bit).
*
* Usage: generate the first combination, where all omitted fields are absent
* (=all zeros), and keep calling this function until the last combination
* (where all omitted fields are 'null', = all ones) is reached.
*
* @return true, if the next combination was successfully generated, or
* false, when called with the last combination */
static bool next_omitted_json_combo(int* omitted_fields, size_t len)
{
for (size_t i = 0; i < len; ++i) {
if (omitted_fields[i] == OMITTED_ABSENT) {
omitted_fields[i] = OMITTED_NULL;
for (size_t j = 0; j < i; ++j) {
if (omitted_fields[j] == OMITTED_NULL) {
omitted_fields[j] = OMITTED_ABSENT;
}
}
return true;
}
}
return false;
}
void Value::generate_json_value(JSON_Tokenizer& json, bool allow_special_float /* = true */)
void Value::generate_json_value(JSON_Tokenizer& json,
bool allow_special_float, /* = true */
bool union_value_list, /* = false */
Ttcn::JsonOmitCombination* omit_combo /* = NULL */)
{
switch (valuetype) {
case V_INT:
......@@ -12727,7 +12690,8 @@ error:
json.put_next_token(JSON_TOKEN_ARRAY_START);
if (!u.val_vs->is_indexed()) {
for (size_t i = 0; i < u.val_vs->get_nof_vs(); ++i) {
u.val_vs->get_v_byIndex(i)->generate_json_value(json);
u.val_vs->get_v_byIndex(i)->generate_json_value(json, allow_special_float,
union_value_list, omit_combo);
}
}
else {
......@@ -12735,7 +12699,8 @@ error:
// look for the entry with index equal to i
for (size_t j = 0; j < u.val_vs->get_nof_ivs(); ++j) {
if (u.val_vs->get_iv_byIndex(j)->get_index()->get_val_Int()->get_val() == (Int)i) {
u.val_vs->get_iv_byIndex(j)->get_value()->generate_json_value(json);
u.val_vs->get_iv_byIndex(j)->get_value()->generate_json_value(json,
allow_special_float, union_value_list, omit_combo);
break;
}
}
......@@ -12748,49 +12713,41 @@ error:
// omitted fields have 2 possible JSON values (the field is absent, or it's
// present with value 'null'), each combination of omitted values must be
// generated
if (omit_combo == NULL) {
FATAL_ERROR("Value::generate_json_value - no combo");
}
size_t len = get_nof_comps();
int* omitted_fields = new int[len]; // stores one combination
// generate the JSON object from the present combination
json.put_next_token(JSON_TOKEN_OBJECT_START);
for (size_t i = 0; i < len; ++i) {
if (get_se_comp_byIndex(i)->get_value()->valuetype == V_OMIT) {
// all omitted fields are absent in the first combination
omitted_fields[i] = OMITTED_ABSENT;
Ttcn::JsonOmitCombination::omit_state_t state = omit_combo->get_state(this, i);
if (state == Ttcn::JsonOmitCombination::OMITTED_ABSENT) {
// the field is absent, don't insert anything
continue;
}
// use the field's alias, if it has one
const char* alias = NULL;
if (my_governor != NULL) {
JsonAST* field_attrib = my_governor->get_comp_byName(
get_se_comp_byIndex(i)->get_name())->get_type()->get_json_attributes();
if (field_attrib != NULL) {
alias = field_attrib->alias;
}
}
json.put_next_token(JSON_TOKEN_NAME, (alias != NULL) ? alias :
get_se_comp_byIndex(i)->get_name().get_ttcnname().c_str());
if (state == Ttcn::JsonOmitCombination::OMITTED_NULL) {
json.put_next_token(JSON_TOKEN_LITERAL_NULL);
}
else {
omitted_fields[i] = NOT_OMITTED;
get_se_comp_byIndex(i)->get_value()->generate_json_value(json,
allow_special_float, union_value_list, omit_combo);
}
}
do {
// generate the JSON object from the present combination
json.put_next_token(JSON_TOKEN_OBJECT_START);
for (size_t i = 0; i < len; ++i) {
if (omitted_fields[i] == OMITTED_ABSENT) {
// the field is absent, don't insert anything
continue;
}
// use the field's alias, if it has one
const char* alias = NULL;
if (my_governor != NULL) {
JsonAST* field_attrib = my_governor->get_comp_byName(
get_se_comp_byIndex(i)->get_name())->get_type()->get_json_attributes();
if (field_attrib != NULL) {
alias = field_attrib->alias;
}
}
json.put_next_token(JSON_TOKEN_NAME, (alias != NULL) ? alias :
get_se_comp_byIndex(i)->get_name().get_ttcnname().c_str());
if (omitted_fields[i] == OMITTED_NULL) {
json.put_next_token(JSON_TOKEN_LITERAL_NULL);
}
else {
get_se_comp_byIndex(i)->get_value()->generate_json_value(json);
}
}
json.put_next_token(JSON_TOKEN_OBJECT_END);
} // generate the next combination, until all combinations have been processed
while (next_omitted_json_combo(omitted_fields, len));
json.put_next_token(JSON_TOKEN_OBJECT_END);
break; }
case V_CHOICE: {
bool as_value = my_governor != NULL &&
bool as_value = !union_value_list && my_governor != NULL &&
my_governor->get_type_refd_last()->get_json_attributes() != NULL &&
my_governor->get_type_refd_last()->get_json_attributes()->as_value;
if (!as_value) {
......@@ -12808,7 +12765,8 @@ error:
json.put_next_token(JSON_TOKEN_NAME, (alias != NULL) ? alias :
get_alt_name().get_ttcnname().c_str());
}
get_alt_value()->generate_json_value(json);
get_alt_value()->generate_json_value(json, allow_special_float,
union_value_list, omit_combo);
if (!as_value) {
json.put_next_token(JSON_TOKEN_OBJECT_END);
}
......@@ -12816,7 +12774,7 @@ error:
case V_REFD: {
Value* v = get_value_refd_last();
if (this != v) {
v->generate_json_value(json);