Commit 7c187762 authored by Botond Baranyi's avatar Botond Baranyi

JSON dec: implemented the 'default' attribute defined in the standard CR 7968 (issue #547)

Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 0863d2a6
......@@ -62,6 +62,10 @@
extern Ttcn::ExtensionAttributes * parse_extattributes(
Ttcn::WithAttribPath *w_attrib_path);
// implemented in compiler.y
extern Common::Value* ttcn3_parse_json_default(
const char* p_str, const Common::Location& str_loc);
namespace Common {
map<Type*, void> Type::RecursionTracker::types;
......@@ -3168,9 +3172,12 @@ namespace Common {
}
}
if (NULL != jsonattrib->default_value) {
if (jsonattrib->default_value.type == JsonAST::JD_STANDARD) {
chk_json_default();
}
else if (jsonattrib->default_value.type == JsonAST::JD_LEGACY) {
chk_json_default_legacy();
}
const size_t nof_extensions = jsonattrib->schema_extensions.size();
if (0 != nof_extensions) {
......@@ -3389,9 +3396,33 @@ namespace Common {
}
}
void Type::chk_json_default()
void Type::chk_json_default()
{
if (jsonattrib->default_value.type != JsonAST::JD_STANDARD || jsonattrib->default_value.str == NULL ||
jsonattrib->default_value.loc == NULL) {
FATAL_ERROR("Type::chk_json_default");
}
Error_Context cntxt(this, "In JSON default value");
Value* val = ttcn3_parse_json_default(jsonattrib->default_value.str, *jsonattrib->default_value.loc);
if (val != NULL) {
val->set_my_governor(this);
val->set_my_scope(my_scope);
val->set_fullname(get_fullname() + ".<JSON_default_value>");
val->set_genname(get_genname_own() + "_json_defval");
chk_this_value_ref(val);
chk_this_value(val, NULL, EXPECTED_CONSTANT, INCOMPLETE_NOT_ALLOWED,
OMIT_NOT_ALLOWED, SUB_CHK, NOT_IMPLICIT_OMIT);
jsonattrib->default_value.val = val;
}
}
void Type::chk_json_default_legacy()
{
const char* dval = jsonattrib->default_value;
if (jsonattrib->default_value.type != JsonAST::JD_LEGACY || jsonattrib->default_value.str == NULL) {
FATAL_ERROR("Type::chk_json_default");
}
Error_Context cntxt(this, "In JSON default value (legacy)");
const char* dval = jsonattrib->default_value.str;
const size_t dval_len = strlen(dval);
Type *last = get_type_refd_last();
bool err = false;
......
......@@ -913,6 +913,7 @@ namespace Common {
void chk_json();
void chk_json_default();
void chk_json_default_legacy();
void chk_json_tag_list();
/** If the type does not have a jsonattrib, create one. */
void force_json();
......
......@@ -1113,13 +1113,35 @@ void Type::generate_code_jsondescriptor(output_struct *target)
if (NULL == jsonattrib) {
target->source.global_vars = mputprintf(target->source.global_vars,
"const TTCN_JSONdescriptor_t %s_json_ = { FALSE, NULL, FALSE, NULL, "
"const TTCN_JSONdescriptor_t %s_json_ = { FALSE, NULL, FALSE, { JD_UNSET, NULL }, "
"FALSE, FALSE, %s, 0, NULL, FALSE, ESCAPE_AS_SHORT };\n"
, get_genname_own().c_str(), as_map ? "TRUE" : "FALSE");
} else {
char* alias = jsonattrib->alias ? mputprintf(NULL, "\"%s\"", jsonattrib->alias) : NULL;
char* def_val = jsonattrib->default_value ?
mputprintf(NULL, "\"%s\"", jsonattrib->default_value) : NULL;
const char* def_type;
char* def_val = NULL;
switch (jsonattrib->default_value.type) {
case JsonAST::JD_UNSET:
def_type = "JD_UNSET";
break;
case JsonAST::JD_LEGACY:
def_type = "JD_LEGACY";
def_val = mprintf(".str = \"%s\"", jsonattrib->default_value.str);
break;
case JsonAST::JD_STANDARD:
def_type = "JD_STANDARD";
Value* v = jsonattrib->default_value.val;
const_def cdef;
Code::init_cdef(&cdef);
generate_code_object(&cdef, v, false);
// Generate the initialization of the default values in the post init function
// because the module parameters are not initialized in the pre init function
target->functions.post_init = v->generate_code_init(target->functions.post_init, v->get_lhs_name().c_str());
Code::merge_cdef(target, &cdef);
Code::free_cdef(&cdef);
def_val = mprintf(".val = &%s", v->get_lhs_name().c_str());
break;
}
char* enum_texts_name;
if (0 != jsonattrib->enum_texts.size()) {
......@@ -1139,13 +1161,13 @@ void Type::generate_code_jsondescriptor(output_struct *target)
}
target->source.global_vars = mputprintf(target->source.global_vars,
"const TTCN_JSONdescriptor_t %s_json_ = { %s, %s, %s, %s, %s, %s, %s, "
"const TTCN_JSONdescriptor_t %s_json_ = { %s, %s, %s, { %s, %s }, %s, %s, %s, "
"%d, %s, %s, %s };\n"
, get_genname_own().c_str()
, jsonattrib->omit_as_null ? "TRUE" : "FALSE"
, alias ? alias : "NULL"
, (jsonattrib->as_value || jsonattrib->tag_list != NULL) ? "TRUE" : "FALSE"
, def_val ? def_val : "NULL"
, def_type, def_val ? def_val : "NULL"
, jsonattrib->metainfo_unbound ? "TRUE" : "FALSE"
, jsonattrib->as_number ? "TRUE" : "FALSE"
, as_map ? "TRUE" : "FALSE"
......@@ -1895,7 +1917,7 @@ void Type::generate_code_Se(output_struct *target)
if (type->jsonattrib) {
cur.jsonOmitAsNull = type->jsonattrib->omit_as_null;
cur.jsonAlias = type->jsonattrib->alias;
cur.jsonDefaultValue = type->jsonattrib->default_value;
cur.jsonDefaultValue = type->jsonattrib->default_value.str;
cur.jsonMetainfoUnbound = type->jsonattrib->metainfo_unbound;
if (type->jsonattrib->tag_list != NULL) {
rawAST_tag_list* tag_list = type->jsonattrib->tag_list;
......@@ -3811,18 +3833,18 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val
}
// insert default value (if any)
if (jsonattrib != NULL && jsonattrib->default_value != NULL) {
if (jsonattrib != NULL && jsonattrib->default_value.str != NULL) {
json.put_next_token(JSON_TOKEN_NAME, "default");
switch (last->typetype) {
case T_BOOL:
json.put_next_token((jsonattrib->default_value[0] == 't') ?
json.put_next_token((jsonattrib->default_value.str[0] == 't') ?
JSON_TOKEN_LITERAL_TRUE : JSON_TOKEN_LITERAL_FALSE);
break;
case T_INT:
case T_REAL:
if (jsonattrib->default_value[0] != 'n' && jsonattrib->default_value[0] != 'i'
&& jsonattrib->default_value[1] != 'i') {
json.put_next_token(JSON_TOKEN_NUMBER, jsonattrib->default_value);
if (jsonattrib->default_value.str[0] != 'n' && jsonattrib->default_value.str[0] != 'i'
&& jsonattrib->default_value.str[1] != 'i') {
json.put_next_token(JSON_TOKEN_NUMBER, jsonattrib->default_value.str);
break;
}
// no break, insert the special float values as strings
......@@ -3833,7 +3855,7 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val
case T_USTR:
case T_VERDICT:
case T_ENUM_T: {
char* default_str = mprintf("\"%s\"", jsonattrib->default_value);
char* default_str = mprintf("\"%s\"", jsonattrib->default_value.str);
json.put_next_token(JSON_TOKEN_STRING, default_str);
Free(default_str);
break; }
......
......@@ -838,11 +838,16 @@ void defEnumClass(const enum_def *edef, output_struct *output)
" size_t value_len = 0;\n"
" boolean error = FALSE;\n"
" size_t dec_len = 0;\n"
" boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();\n"
" if (use_default) {\n"
" boolean use_default = FALSE;\n"
" if (p_td.json->default_value.type == JD_STANDARD && 0 == p_tok.get_buffer_length()) {\n"
" *this = *static_cast<const %s*>(p_td.json->default_value.val);\n"
" return dec_len;\n"
" }\n"
" if (p_td.json->default_value.type == JD_LEGACY && 0 == p_tok.get_buffer_length()) {\n"
// No JSON data in the buffer -> use default value
" value = const_cast<char*>(p_td.json->default_value);\n"
" value = const_cast<char*>(p_td.json->default_value.str);\n"
" value_len = strlen(value);\n"
" use_default = TRUE;\n"
" } else {\n"
" dec_len = p_tok.get_next_token(&token, &value, &value_len);\n"
" }\n"
......@@ -902,7 +907,7 @@ void defEnumClass(const enum_def *edef, output_struct *output)
" }\n"
" return (int)dec_len;\n"
"}\n\n"
, name, edef->elements[0].name, enum_type, unknown_value, enum_type
, name, name, edef->elements[0].name, enum_type, unknown_value, enum_type
, unbound_value, unbound_value);
}
......
......@@ -3266,10 +3266,13 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc)
char* generate_json_decoder(char* src, const struct_def* sdef)
{
src = mputprintf(src,
"int %s::JSON_decode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok, "
"int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, "
"boolean p_silent, boolean p_parent_is_map, int)\n"
"{\n", sdef->name,
((sdef->nElements == 1 && !sdef->jsonAsValue) || sdef->jsonAsMapPossible) ? " p_td" : "");
"{\n"
" if (p_td.json->default_value.type == JD_STANDARD && 0 == p_tok.get_buffer_length()) {\n"
" *this = *static_cast<const %s*>(p_td.json->default_value.val);\n"
" return 0;\n"
" }\n", sdef->name, sdef->name);
if (sdef->nElements == 1) {
if (!sdef->jsonAsValue) {
......@@ -6897,10 +6900,14 @@ static void defEmptyRecordClass(const struct_def *sdef,
src = mputprintf(src,
"int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent, boolean, int)\n"
"{\n"
" if (NULL != p_td.json->default_value && 0 == p_tok.get_buffer_length()) {\n"
" if (p_td.json->default_value.type == JD_STANDARD && 0 == p_tok.get_buffer_length()) {\n"
" *this = *static_cast<const %s*>(p_td.json->default_value.val);\n"
" return 0;\n"
" }\n"
" if (p_td.json->default_value.type != JD_UNSET && 0 == p_tok.get_buffer_length()) {\n"
// use the default value
" bound_flag = TRUE;\n"
" return strlen(p_td.json->default_value);\n"
" return strlen(p_td.json->default_value.str);\n"
" }\n"
" json_token_t token = JSON_TOKEN_NONE;\n"
" size_t dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
......@@ -6919,7 +6926,7 @@ static void defEmptyRecordClass(const struct_def *sdef,
" bound_flag = TRUE;\n\n"
" return (int)dec_len;\n"
"}\n\n"
, name);
, name, name);
}
if (oer_needed) {
......
......@@ -1579,11 +1579,15 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
src = mputprintf(src,
"int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent, boolean, int)\n"
"{\n"
" if (NULL != p_td.json->default_value && 0 == p_tok.get_buffer_length()) {\n"
" if (p_td.json->default_value.type == JD_STANDARD && 0 == p_tok.get_buffer_length()) {\n"
" *this = *static_cast<const %s*>(p_td.json->default_value.val);\n"
" return 0;\n"
" }\n"
" if (p_td.json->default_value.type == JD_LEGACY && 0 == p_tok.get_buffer_length()) {\n"
// use the default value (currently only the empty array can be set as
// default value for this type)
" set_size(0);\n"
" return strlen(p_td.json->default_value);\n"
" return strlen(p_td.json->default_value.str);\n"
" }\n"
" json_token_t token = JSON_TOKEN_NONE;\n"
" size_t dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
......@@ -1653,7 +1657,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
" }\n\n"
" return (int)dec_len;\n"
"}\n\n"
, name, type, type, type);
, name, name, type, type, type);
}
if (oer_needed) {
// OER encode, RT1
......@@ -3105,6 +3109,16 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
src = mputprintf(src,
"int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent, boolean, int)\n"
"{\n"
" if (p_td.json->default_value.type == JD_STANDARD && 0 == p_tok.get_buffer_length()) {\n"
" *this = *static_cast<const %s*>(p_td.json->default_value.val);\n"
" return 0;\n"
" }\n"
" if (p_td.json->default_value.type == JD_LEGACY && 0 == p_tok.get_buffer_length()) {\n"
// use the default value (currently only the empty array can be set as
// default value for this type)
" set_size(0);\n"
" return strlen(p_td.json->default_value.str);\n"
" }\n"
" json_token_t token = JSON_TOKEN_NONE;\n"
" size_t dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
" if (JSON_TOKEN_ERROR == token) {\n"
......@@ -3167,7 +3181,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
" }\n\n"
" return (int)dec_len;\n"
"}\n\n"
, name, type);
, name, name, type);
}
if (oer_needed) {
// OER encode, RT1, mem. alloc. optimised
......
......@@ -14,6 +14,7 @@
#include "../../common/memory.h"
#include <cstddef>
#include <cstdio>
#include "../Value.hh"
void JsonSchemaExtension::init(char* p_key, char* p_value)
{
......@@ -38,7 +39,10 @@ void JsonAST::init_JsonAST()
omit_as_null = false;
alias = NULL;
as_value = false;
default_value = NULL;
default_value.type = JD_UNSET;
default_value.str = NULL;
default_value.val = NULL;
default_value.loc = NULL;
metainfo_unbound = false;
as_number = false;
tag_list = NULL;
......@@ -55,7 +59,9 @@ JsonAST::JsonAST(const JsonAST *other_val)
omit_as_null = other_val->omit_as_null;
alias = (NULL != other_val->alias) ? mcopystr(other_val->alias) : NULL;
as_value = other_val->as_value;
default_value = (NULL != other_val->default_value) ? mcopystr(other_val->default_value) : NULL;
default_value.type = other_val->default_value.type;
default_value.str = (NULL != other_val->default_value.str) ? mcopystr(other_val->default_value.str) : NULL;
default_value.val = (NULL != other_val->default_value.val) ? other_val->default_value.val->clone() : NULL;
as_number = other_val->as_number;
for (size_t i = 0; i < other_val->schema_extensions.size(); ++i) {
schema_extensions.add(new JsonSchemaExtension(*other_val->schema_extensions[i]));
......@@ -75,7 +81,9 @@ JsonAST::JsonAST(const JsonAST *other_val)
JsonAST::~JsonAST()
{
Free(alias);
Free(default_value);
Free(default_value.str);
delete default_value.val;
delete default_value.loc;
for (size_t i = 0; i < schema_extensions.size(); ++i) {
delete schema_extensions[i];
}
......@@ -93,7 +101,7 @@ JsonAST::~JsonAST()
boolean JsonAST::empty() const
{
return omit_as_null == false && alias == NULL && as_value == false &&
default_value == NULL && metainfo_unbound == false && as_number == false &&
default_value.type == JD_UNSET && metainfo_unbound == false && as_number == false &&
tag_list == NULL && as_map == false && enum_texts.size() == 0 &&
use_null == false && type_indicator != JSON_OBJECT &&
type_indicator != JSON_LITERAL &&
......@@ -167,8 +175,9 @@ void JsonAST::print_JsonAST() const
if (as_value) {
printf("Encoding unions as JSON value\n\r");
}
if (default_value) {
printf("Default value: %s\n\r", default_value);
if (default_value.type != JD_UNSET) {
printf("Default value%s: %s\n\r", default_value.type == JD_LEGACY ? " (legacy)" : "",
default_value.type == JD_LEGACY ? default_value.str : default_value.val->create_stringRepr().c_str());
}
if (as_number) {
printf("Encoding enumerated values as numbers\n\r");
......
......@@ -55,6 +55,11 @@ public:
ESCAPE_AS_USI,
ESCAPE_AS_TRANSPARENT
};
enum json_default_type {
JD_UNSET, // no default value set
JD_LEGACY, // legacy default value set through the 'JSON: default' variant attribute
JD_STANDARD // standard-compliant default value set through the 'default' variant attribute
};
private:
void init_JsonAST();
JsonAST(const JsonAST&);
......@@ -63,7 +68,12 @@ public:
boolean omit_as_null;
char* alias;
boolean as_value;
char* default_value;
struct {
json_default_type type;
char* str;
Common::Value* val;
Common::Location* loc;
} default_value;
vector<JsonSchemaExtension> schema_extensions;
boolean metainfo_unbound;
boolean as_number;
......
......@@ -197,6 +197,7 @@ LINEMARKER {NUMBER}{WHITESPACE}+\"([^\\\"\r\n]|\\[^\r\n])*\"
UID [uU][+]?[0-9A-Fa-f]{1,8}
TITAN "$#&&&(#TITANERRONEOUS$#&&^#% "
TITAN2 "$#&&&(#TITANJSONDEFAULT$#&&^#% "
%x SC_blockcomment SC_cstring
%x SC_binstring SC_binstring_bad
......@@ -246,6 +247,10 @@ TITAN "$#&&&(#TITANERRONEOUS$#&&^#% "
}
}
{TITAN2} {
RETURN(TitanJsonDefaultHackKeyword);
}
/* Eat up comments and whitespaces */
"/*" {
......
......@@ -76,11 +76,14 @@ const char *infile = NULL;
static Ttcn::Module *act_ttcn3_module = NULL;
static Ttcn::ErroneousAttributeSpec *act_ttcn3_erroneous_attr_spec = NULL;
static Common::Value* act_json_default = NULL;
bool is_erroneous_parsed = false;
bool is_json_default_parsed = false;
static void ttcn3_error(const char *str);
static Group* act_group = NULL;
extern string anytype_field(const string& type_name);
static bool anytype_access = false;
static bool parsing_error = false;
#ifndef NDEBUG
......@@ -649,6 +652,7 @@ static const string anyname("anytype");
* This magic requires the presence of the unused keywords.
* (It can return an ApplyKeyword if not preceded by a dot) */
%token TitanErroneousHackKeyword
%token TitanJsonDefaultHackKeyword
%token ActionKeyword
%token ActivateKeyword
%token AddressKeyword
......@@ -2082,11 +2086,12 @@ reduce in case of conflicts.
GrammarRoot:
TTCN3Module
{
if (is_erroneous_parsed) {
if (is_erroneous_parsed || is_json_default_parsed) {
delete act_ttcn3_module;
act_ttcn3_module = NULL;
Location loc(infile, @1);
loc.error("The erroneous attribute cannot be a TTCN-3 module.");
loc.error("The %s cannot be a TTCN-3 module.",
is_json_default_parsed ? "JSON default value" : "erroneous attribute");
}
}
| TitanErroneousHackKeyword ErroneousAttributeSpec
......@@ -2095,7 +2100,29 @@ GrammarRoot:
delete act_ttcn3_erroneous_attr_spec;
act_ttcn3_erroneous_attr_spec = NULL;
Location loc(infile, @$);
loc.error("File `%s' does not contain a TTCN-3 module.", infile);
if (is_json_default_parsed) {
loc.error("JSON default value expected instead of erroneous attribute.");
}
else {
loc.error("File `%s' does not contain a TTCN-3 module.", infile);
}
}
}
| TitanJsonDefaultHackKeyword Expression
{
act_json_default = $2;
if (!is_json_default_parsed || parsing_error) {
delete act_json_default;
act_json_default = NULL;
if (!is_json_default_parsed) {
Location loc(infile, @2);
if (is_erroneous_parsed) {
loc.error("Erroneous attribute expected instead of JSON default value.");
}
else {
loc.error("File `%s' does not contain a TTCN-3 module.", infile);
}
}
}
}
| error
......@@ -11431,6 +11458,7 @@ static void ttcn3_error(const char *str)
// the most recently parsed token is unknown
loc.error("%s", str);
}
parsing_error = true;
}
int ttcn3_parse_file(const char* filename, boolean generate_code)
......@@ -11448,6 +11476,7 @@ int ttcn3_parse_file(const char* filename, boolean generate_code)
init_ttcn3_lex();
is_erroneous_parsed = false;
is_json_default_parsed = false;
NOTIFY("Parsing TTCN-3 module `%s'...", filename);
int retval = ttcn3_parse();
......@@ -11471,6 +11500,7 @@ Ttcn::ErroneousAttributeSpec* ttcn3_parse_erroneous_attr_spec_string(
const char* p_str, const Common::Location& str_loc)
{
is_erroneous_parsed = true;
is_json_default_parsed = false;
act_ttcn3_erroneous_attr_spec = NULL;
string titan_err_str("$#&&&(#TITANERRONEOUS$#&&^#% ");
size_t hack_str_len = titan_err_str.size();
......@@ -11490,6 +11520,30 @@ Ttcn::ErroneousAttributeSpec* ttcn3_parse_erroneous_attr_spec_string(
return act_ttcn3_erroneous_attr_spec;
}
Common::Value* ttcn3_parse_json_default(
const char* p_str, const Common::Location& str_loc)
{
is_erroneous_parsed = false;
is_json_default_parsed = true;
act_json_default = NULL;
string titan_err_str("$#&&&(#TITANJSONDEFAULT$#&&^#% ");
size_t hack_str_len = titan_err_str.size();
string *parsed_string = parse_charstring_value(p_str, str_loc);
titan_err_str += *parsed_string;
delete parsed_string;
init_erroneous_lex(str_loc.get_filename(), str_loc.get_first_line(), str_loc.get_first_column()-hack_str_len+1);
yy_buffer_state *flex_buffer = ttcn3__scan_string(titan_err_str.c_str());
if (flex_buffer == NULL) {
ERROR("Flex buffer creation failed.");
return NULL;
}
yyparse();
ttcn3_lex_destroy();
free_dot_flag_stuff();
return act_json_default;
}
#ifndef NDEBUG
static void yyprint(FILE *file, int type, const YYSTYPE& value)
{
......
......@@ -491,7 +491,7 @@ literal RETURN(XKWliteral);
else yylval.str = mcopystr(yytext);
RETURN(XJsonValueSegment);
}
[)] { BEGIN(jsoncodec); RETURN(XJsonValueEnd); }
[)] { BEGIN(INITIAL); RETURN(XJsonValueEnd); }
[\"][\"] { yylval.str = mcopystr("\\\""); RETURN(XJsonValueSegment); }
[^\"\\)]+ { yylval.str = mcopystr(yytext); RETURN(XJsonValueSegment); }
}
......
......@@ -1860,7 +1860,8 @@ XAsValue:
;
XDefault:
XKWdefault XOptSpaces XJsonValue { jsonstruct->default_value = $3; }
XKWdefault XOptSpaces XJsonValue
{ jsonstruct->default_value.str = $3; jsonstruct->default_value.type = JsonAST::JD_LEGACY; }
;
XExtend:
......@@ -1938,7 +1939,12 @@ JAsValue:
;
JDefault:
XKWdefault XOptSpaces XJsonValue XOptSpaces { jsonstruct->default_value = $3; }
XKWdefault XOptSpaces XJsonValue XOptSpaces
{
jsonstruct->default_value.str = $3;
jsonstruct->default_value.type = JsonAST::JD_STANDARD;
jsonstruct->default_value.loc = new Common::Location(infile, @3);
}
;
JExtend:
......
......@@ -2195,10 +2195,10 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
// JSON decode
src = mputprintf(src,
"int %s::JSON_decode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok, "
"int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, "
"boolean p_silent, boolean, int p_chosen_field)\n"
"{\n"
, name, sdef->nElements > 0 && !sdef->jsonAsValue ? " p_td" : "");
, name);
if (sdef->nElements > 0) {
src = mputprintf(src,
" if (0 <= p_chosen_field && %d > p_chosen_field) {\n"
......@@ -2211,10 +2211,14 @@ void defUnionClass(struct_def const *sdef, output_struct *output)
, (int)i, at_field, sdef->elements[i].name
, sdef->elements[i].typedescrname);
}
src = mputstr(src,
src = mputprintf(src,
" }\n"
" }\n"
" json_token_t j_token = JSON_TOKEN_NONE;\n");
" if (p_td.json->default_value.type == JD_STANDARD && 0 == p_tok.get_buffer_length()) {\n"
" *this = *static_cast<const %s*>(p_td.json->default_value.val);\n"
" return 0;\n"
" }\n"
" json_token_t j_token = JSON_TOKEN_NONE;\n", name);
if (!sdef->jsonAsValue) {
src = mputstr(src,
" if (p_td.json->as_value) {\n");
......
......@@ -1204,11 +1204,16 @@ int BITSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_
size_t value_len = 0;
boolean error = FALSE;
size_t dec_len = 0;
boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
if (use_default) {
boolean use_default = FALSE;
if (p_td.json->default_value.type == JD_STANDARD && 0 == p_tok.get_buffer_length()) {
*this = *static_cast<const BITSTRING*>(p_td.json->default_value.val);
return dec_len;
}
if (p_td.json->default_value.type == JD_LEGACY && 0 == p_tok.get_buffer_length()) {
// No JSON data in the buffer -> use default value
value = const_cast<char*>(p_td.json->default_value);
value = const_cast<char*>(p_td.json->default_value.str);
value_len = strlen(value);
use_default = TRUE;
} else {
dec_len = p_tok.get_next_token(&token, &value, &value_len);
}
......
......@@ -770,9 +770,13 @@ int BOOLEAN::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_to
{
json_token_t token = JSON_TOKEN_NONE;
size_t dec_len = 0;
if (p_td.json->default_value && 0 == p_tok.get_buffer_length()) {
if (p_td.json->default_value.type == JD_STANDARD && 0 == p_tok.get_buffer_length()) {
*this = *static_cast<const BOOLEAN*>(p_td.json->default_value.val);
return dec_len;
}