Commit 5d4b0ac7 authored by Jeno Attila Balasko's avatar Jeno Attila Balasko Committed by Gerrit Code Review
Browse files

Merge "Implemented JSON attribute 'text ... as ...', and fixed other JSON errors (bug 540262)"

parents 52faf3ac a06ecc81
...@@ -3004,10 +3004,15 @@ namespace Common { ...@@ -3004,10 +3004,15 @@ namespace Common {
"record of, set of, array or field of a record or set"); "record of, set of, array or field of a record or set");
} }
} }
if (jsonattrib->as_number && if (jsonattrib->as_number) {
get_type_refd_last()->get_typetype_ttcn3() != T_ENUM_T) { if (get_type_refd_last()->get_typetype_ttcn3() != T_ENUM_T) {
error("Invalid attribute, 'as number' is only allowed for enumerated " error("Invalid attribute, 'as number' is only allowed for enumerated "
"types"); "types");
}
else if (0 != jsonattrib->enum_texts.size()) {
warning("Attribute 'text ... as ...' will be ignored, because the "
"enumerated values are encoded as numbers");
}
} }
if (NULL != jsonattrib->tag_list) { if (NULL != jsonattrib->tag_list) {
...@@ -3041,6 +3046,35 @@ namespace Common { ...@@ -3041,6 +3046,35 @@ namespace Common {
} }
} }
} }
if (0 != jsonattrib->enum_texts.size()) {
Type* last = get_type_refd_last();
if (T_ENUM_T != last->get_typetype_ttcn3()) {
error("Invalid attribute, 'text ... as ...' requires an enumerated "
"type");
}
else {
for (size_t i = 0; i < jsonattrib->enum_texts.size(); ++i) {
Identifier id(Identifier::ID_TTCN,
string(jsonattrib->enum_texts[i]->from), true);
if (!last->has_ei_withName(id)) {
error("Attribute 'text ... as ...' refers to invalid enumerated "
"value '%s'", jsonattrib->enum_texts[i]->from);
}
else {
jsonattrib->enum_texts[i]->index = static_cast<int>(
last->get_eis_index_byName(id));
for (size_t j = 0; j < i; ++j) {
if (jsonattrib->enum_texts[j]->index ==
jsonattrib->enum_texts[i]->index) {
error("Duplicate attribute 'text ... as ...' for enumerated "
"value '%s'", jsonattrib->enum_texts[i]->from);
}
}
}
}
}
}
} }
} }
...@@ -7631,7 +7665,11 @@ namespace Common { ...@@ -7631,7 +7665,11 @@ namespace Common {
{ {
Type *t = this; Type *t = this;
while (true) { while (true) {
if (t->has_encoding(CT_JSON)) return t->get_genname_own(my_scope); if ((t->jsonattrib != NULL && !t->jsonattrib->empty()) ||
(t->ownertype == OT_RECORD_OF && t->parent_type->jsonattrib != NULL &&
t->parent_type->jsonattrib->as_map)) {
return t->get_genname_own(my_scope);
}
else if (t->is_ref()) t = t->get_type_refd(); else if (t->is_ref()) t = t->get_type_refd();
else break; else break;
} }
......
...@@ -1098,15 +1098,33 @@ void Type::generate_code_jsondescriptor(output_struct *target) ...@@ -1098,15 +1098,33 @@ void Type::generate_code_jsondescriptor(output_struct *target)
if (NULL == jsonattrib) { if (NULL == jsonattrib) {
target->source.global_vars = mputprintf(target->source.global_vars, 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, NULL, "
"FALSE, FALSE, %s };\n" "FALSE, FALSE, %s, 0, NULL };\n"
, get_genname_own().c_str(), as_map ? "TRUE" : "FALSE"); , get_genname_own().c_str(), as_map ? "TRUE" : "FALSE");
} else { } else {
char* alias = jsonattrib->alias ? mputprintf(NULL, "\"%s\"", jsonattrib->alias) : NULL; char* alias = jsonattrib->alias ? mputprintf(NULL, "\"%s\"", jsonattrib->alias) : NULL;
char* def_val = jsonattrib->default_value ? char* def_val = jsonattrib->default_value ?
mputprintf(NULL, "\"%s\"", jsonattrib->default_value) : NULL; mputprintf(NULL, "\"%s\"", jsonattrib->default_value) : NULL;
char* enum_texts_name;
if (0 != jsonattrib->enum_texts.size()) {
enum_texts_name = mprintf("%s_json_enum_texts", get_genname_own().c_str());
target->source.global_vars = mputprintf(target->source.global_vars,
"const JsonEnumText %s[] = { ", enum_texts_name);
for (size_t i = 0; i < jsonattrib->enum_texts.size(); ++i) {
target->source.global_vars = mputprintf(target->source.global_vars,
"%s{ %d, \"%s\" }", i == 0 ? "" : ", ",
jsonattrib->enum_texts[i]->index, jsonattrib->enum_texts[i]->to);
}
target->source.global_vars = mputstr(target->source.global_vars,
" };\n");
}
else {
enum_texts_name = mcopystr("NULL");
}
target->source.global_vars = mputprintf(target->source.global_vars, target->source.global_vars = mputprintf(target->source.global_vars,
"const TTCN_JSONdescriptor_t %s_json_ = { %s, %s, %s, %s, %s, %s, %s };\n" "const TTCN_JSONdescriptor_t %s_json_ = { %s, %s, %s, %s, %s, %s, %s, "
"%d, %s };\n"
, get_genname_own().c_str() , get_genname_own().c_str()
, jsonattrib->omit_as_null ? "TRUE" : "FALSE" , jsonattrib->omit_as_null ? "TRUE" : "FALSE"
, alias ? alias : "NULL" , alias ? alias : "NULL"
...@@ -1114,9 +1132,12 @@ void Type::generate_code_jsondescriptor(output_struct *target) ...@@ -1114,9 +1132,12 @@ void Type::generate_code_jsondescriptor(output_struct *target)
, def_val ? def_val : "NULL" , def_val ? def_val : "NULL"
, jsonattrib->metainfo_unbound ? "TRUE" : "FALSE" , jsonattrib->metainfo_unbound ? "TRUE" : "FALSE"
, jsonattrib->as_number ? "TRUE" : "FALSE" , jsonattrib->as_number ? "TRUE" : "FALSE"
, as_map ? "TRUE" : "FALSE"); , as_map ? "TRUE" : "FALSE"
, static_cast<int>(jsonattrib->enum_texts.size())
, enum_texts_name);
Free(alias); Free(alias);
Free(def_val); Free(def_val);
Free(enum_texts_name);
} }
} }
...@@ -1418,7 +1439,7 @@ void Type::generate_code_Choice(output_struct *target) ...@@ -1418,7 +1439,7 @@ void Type::generate_code_Choice(output_struct *target)
case T_SEQOF: case T_SEQOF:
case T_SETOF: case T_SETOF:
case T_ARRAY: case T_ARRAY:
sdef.elements[i].jsonValueType = JSON_ARRAY; sdef.elements[i].jsonValueType = JSON_ARRAY | JSON_OBJECT;
break; break;
default: default:
FATAL_ERROR("Type::generate_code_Choice - invalid field type %d", tt); FATAL_ERROR("Type::generate_code_Choice - invalid field type %d", tt);
......
...@@ -802,8 +802,23 @@ void defEnumClass(const enum_def *edef, output_struct *output) ...@@ -802,8 +802,23 @@ void defEnumClass(const enum_def *edef, output_struct *output)
" \"Encoding an unbound value of enumerated type %s.\");\n" " \"Encoding an unbound value of enumerated type %s.\");\n"
" return -1;\n" " return -1;\n"
" }\n\n" " }\n\n"
" char* tmp_str = p_td.json->as_number ? mprintf(\"%%d\", enum_value) : " " char* tmp_str;\n"
"mprintf(\"\\\"%%s\\\"\", enum_to_str(enum_value));\n" " if (p_td.json->as_number) {"
" tmp_str = mprintf(\"%%d\", enum_value);\n"
" }\n"
" else {\n"
" boolean text_found = false;\n"
" for (size_t i = 0; i < p_td.json->nof_enum_texts; ++i) {\n"
" if (p_td.json->enum_texts[i].index == enum_value) {\n"
" tmp_str = mprintf(\"\\\"%%s\\\"\", p_td.json->enum_texts[i].text);\n"
" text_found = true;\n"
" break;\n"
" }\n"
" }\n"
" if (!text_found) {\n"
" tmp_str = mprintf(\"\\\"%%s\\\"\", enum_to_str(enum_value));\n"
" }\n"
" }\n"
" int enc_len = p_tok.put_next_token(p_td.json->as_number ? " " int enc_len = p_tok.put_next_token(p_td.json->as_number ? "
"JSON_TOKEN_NUMBER : JSON_TOKEN_STRING, tmp_str);\n" "JSON_TOKEN_NUMBER : JSON_TOKEN_STRING, tmp_str);\n"
" Free(tmp_str);\n" " Free(tmp_str);\n"
...@@ -835,7 +850,17 @@ void defEnumClass(const enum_def *edef, output_struct *output) ...@@ -835,7 +850,17 @@ void defEnumClass(const enum_def *edef, output_struct *output)
" else if ((JSON_TOKEN_STRING == token && !p_td.json->as_number) || use_default) {\n" " else if ((JSON_TOKEN_STRING == token && !p_td.json->as_number) || use_default) {\n"
" if (use_default || (value_len > 2 && value[0] == '\\\"' && value[value_len - 1] == '\\\"')) {\n" " if (use_default || (value_len > 2 && value[0] == '\\\"' && value[value_len - 1] == '\\\"')) {\n"
" if (!use_default) value[value_len - 1] = 0;\n" " if (!use_default) value[value_len - 1] = 0;\n"
" enum_value = str_to_enum(value + (use_default ? 0 : 1));\n" " boolean text_found = false;\n"
" for (size_t i = 0; i < p_td.json->nof_enum_texts; ++i) {\n"
" if (strcmp(p_td.json->enum_texts[i].text, value + (use_default ? 0 : 1)) == 0) {\n"
" enum_value = static_cast<%s>(p_td.json->enum_texts[i].index);\n"
" text_found = true;\n"
" break;\n"
" }\n"
" }\n"
" if (!text_found) {\n"
" enum_value = str_to_enum(value + (use_default ? 0 : 1));\n"
" }\n"
" if (!use_default) value[value_len - 1] = '\\\"';\n" " if (!use_default) value[value_len - 1] = '\\\"';\n"
" if (%s == enum_value) {\n" " if (%s == enum_value) {\n"
" error = TRUE;\n" " error = TRUE;\n"
...@@ -871,7 +896,7 @@ void defEnumClass(const enum_def *edef, output_struct *output) ...@@ -871,7 +896,7 @@ void defEnumClass(const enum_def *edef, output_struct *output)
" }\n" " }\n"
" return (int)dec_len;\n" " return (int)dec_len;\n"
"}\n\n" "}\n\n"
, name, unknown_value, enum_type, unbound_value, unbound_value); , name, enum_type, unknown_value, enum_type, unbound_value, unbound_value);
} }
if (oer_needed) { if (oer_needed) {
......
...@@ -27,6 +27,12 @@ JsonSchemaExtension::~JsonSchemaExtension() ...@@ -27,6 +27,12 @@ JsonSchemaExtension::~JsonSchemaExtension()
Free(value); Free(value);
} }
JsonEnumText::~JsonEnumText()
{
Free(from);
Free(to);
}
void JsonAST::init_JsonAST() void JsonAST::init_JsonAST()
{ {
omit_as_null = false; omit_as_null = false;
...@@ -53,6 +59,10 @@ JsonAST::JsonAST(const JsonAST *other_val) ...@@ -53,6 +59,10 @@ JsonAST::JsonAST(const JsonAST *other_val)
} }
metainfo_unbound = other_val->metainfo_unbound; metainfo_unbound = other_val->metainfo_unbound;
as_map = other_val->as_map; as_map = other_val->as_map;
for (size_t i = 0; i < other_val->enum_texts.size(); ++i) {
enum_texts.add(new JsonEnumText(mcopystr(other_val->enum_texts[i]->from),
mcopystr(other_val->enum_texts[i]->to)));
}
} }
} }
...@@ -68,6 +78,17 @@ JsonAST::~JsonAST() ...@@ -68,6 +78,17 @@ JsonAST::~JsonAST()
free_rawAST_tag_list(tag_list); free_rawAST_tag_list(tag_list);
delete tag_list; delete tag_list;
} }
for (size_t i = 0; i < enum_texts.size(); ++i) {
delete enum_texts[i];
}
enum_texts.clear();
}
boolean JsonAST::empty() const
{
return omit_as_null == false && alias == NULL && as_value == false &&
default_value == NULL && metainfo_unbound == false && as_number == false &&
tag_list == NULL && as_map == false && enum_texts.size() == 0;
} }
void JsonAST::print_JsonAST() const void JsonAST::print_JsonAST() const
...@@ -124,4 +145,11 @@ void JsonAST::print_JsonAST() const ...@@ -124,4 +145,11 @@ void JsonAST::print_JsonAST() const
if (as_map) { if (as_map) {
printf("Encoding elements into a map of key-value pairs.\n\r"); printf("Encoding elements into a map of key-value pairs.\n\r");
} }
if (0 != enum_texts.size()) {
printf("Enum texts:");
for (size_t i = 0; i < enum_texts.size(); ++i) {
printf(" '%s' -> '%s'", enum_texts[i]->from, enum_texts[i]->to);
}
printf("\n\r");
}
} }
...@@ -29,6 +29,14 @@ public: ...@@ -29,6 +29,14 @@ public:
~JsonSchemaExtension(); ~JsonSchemaExtension();
}; };
struct JsonEnumText {
char* from;
char* to;
int index; // set during semantic analysis
JsonEnumText(char* p_from, char* p_to): from(p_from), to(p_to) {}
~JsonEnumText();
};
class JsonAST { class JsonAST {
private: private:
void init_JsonAST(); void init_JsonAST();
...@@ -44,11 +52,14 @@ class JsonAST { ...@@ -44,11 +52,14 @@ class JsonAST {
boolean as_number; boolean as_number;
rawAST_tag_list* tag_list; rawAST_tag_list* tag_list;
boolean as_map; boolean as_map;
vector<JsonEnumText> enum_texts;
JsonAST() { init_JsonAST(); } JsonAST() { init_JsonAST(); }
JsonAST(const JsonAST *other_val); JsonAST(const JsonAST *other_val);
~JsonAST(); ~JsonAST();
boolean empty() const;
void print_JsonAST() const; void print_JsonAST() const;
}; };
......
...@@ -1505,9 +1505,49 @@ XERattribute: ...@@ -1505,9 +1505,49 @@ XERattribute:
} }
| text | text
{ {
xerstruct->text_ = (NamespaceSpecification *)Realloc(xerstruct->text_, if (selected_codec == Common::Type::CT_XER || legacy_codec_handling) {
++xerstruct->num_text_ * sizeof(NamespaceSpecification)); xerstruct->text_ = (NamespaceSpecification *)Realloc(xerstruct->text_,
xerstruct->text_[xerstruct->num_text_-1] = $1; ++xerstruct->num_text_ * sizeof(NamespaceSpecification));
xerstruct->text_[xerstruct->num_text_-1] = $1;
}
if (selected_codec != Common::Type::CT_XER) {
XerAttributes::NameChange special;
special.nn_ = $1.prefix;
switch (special.kw_) {
case NamespaceSpecification::NO_MANGLING:
case NamespaceSpecification::CAPITALIZED:
case NamespaceSpecification::UNCAPITALIZED:
case NamespaceSpecification::UPPERCASED:
case NamespaceSpecification::LOWERCASED:
case NamespaceSpecification::ALL:
if (!legacy_codec_handling &&
selected_codec == Common::Type::CT_JSON) {
Common::Location loc(infile, @$);
loc.error("This format is not supported for the JSON codec");
}
break;
default: // it's a real string
if (selected_codec == Common::Type::CT_JSON ||
legacy_codec_handling) {
if (legacy_codec_handling) {
// in this case the strings are saved in both the XML and JSON
// structs, so we can't use the same strings
jsonstruct->enum_texts.add(
new JsonEnumText(mcopystr($1.prefix), mcopystr($1.uri)));
}
else {
jsonstruct->enum_texts.add(
new JsonEnumText($1.prefix, $1.uri));
}
json_f = true;
}
else {
Free($1.prefix);
Free($1.uri);
}
break;
}
}
} }
| XKWuntagged { xerstruct->untagged_ = true; } | XKWuntagged { xerstruct->untagged_ = true; }
| XKWuseNil { xerstruct->useNil_ = true; } | XKWuseNil { xerstruct->useNil_ = true; }
......
...@@ -1405,7 +1405,8 @@ int CHARSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, ...@@ -1405,7 +1405,8 @@ int CHARSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
depth = reader.Depth(); depth = reader.Depth();
} }
else if ((depth != -1 || omit_tag) else if ((depth != -1 || omit_tag)
&& (XML_READER_TYPE_TEXT == type || XML_READER_TYPE_CDATA == type || (omit_tag && XML_READER_TYPE_ATTRIBUTE))) && (XML_READER_TYPE_TEXT == type || XML_READER_TYPE_CDATA == type ||
(omit_tag && XML_READER_TYPE_ATTRIBUTE == type)))
// Process #text node if we already processed the element node, or // Process #text node if we already processed the element node, or
// there is no element node because UNTAGGED is in effect. // there is no element node because UNTAGGED is in effect.
{ {
......
...@@ -32,55 +32,55 @@ ...@@ -32,55 +32,55 @@
#include <sys/types.h> #include <sys/types.h>
// JSON descriptors for base types // JSON descriptors for base types
const TTCN_JSONdescriptor_t INTEGER_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t INTEGER_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t FLOAT_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t FLOAT_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t BOOLEAN_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t BOOLEAN_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t BITSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t BITSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t HEXSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t HEXSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t OCTETSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t OCTETSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t CHARSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t CHARSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t UNIVERSAL_CHARSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t UNIVERSAL_CHARSTRING_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t VERDICTTYPE_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t VERDICTTYPE_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t GeneralString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t GeneralString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t NumericString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t NumericString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t UTF8String_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t UTF8String_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t PrintableString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t PrintableString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t UniversalString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t UniversalString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t BMPString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t BMPString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t GraphicString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t GraphicString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t IA5String_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t IA5String_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t TeletexString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t TeletexString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t VideotexString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t VideotexString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t VisibleString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t VisibleString_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t ASN_NULL_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t ASN_NULL_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t OBJID_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t OBJID_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t ASN_ROID_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t ASN_ROID_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t ASN_ANY_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t ASN_ANY_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
const TTCN_JSONdescriptor_t ENUMERATED_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE }; const TTCN_JSONdescriptor_t ENUMERATED_json_ = { FALSE, NULL, FALSE, NULL, FALSE, FALSE, FALSE, 0, NULL };
......
...@@ -21,6 +21,12 @@ class JSON_Tokenizer; ...@@ -21,6 +21,12 @@ class JSON_Tokenizer;
class CHARSTRING; class CHARSTRING;
class INTEGER; class INTEGER;
/** Enumerated text change structure */
struct JsonEnumText {
int index;
const char* text;
};
/** Descriptor for JSON encoding/decoding during runtime */ /** Descriptor for JSON encoding/decoding during runtime */
struct TTCN_JSONdescriptor_t struct TTCN_JSONdescriptor_t
{ {
...@@ -73,6 +79,12 @@ struct TTCN_JSONdescriptor_t ...@@ -73,6 +79,12 @@ struct TTCN_JSONdescriptor_t
* a non-optional universal charstring. * a non-optional universal charstring.
* Example: { "key1" : value1, "key2" : value2 } */ * Example: { "key1" : value1, "key2" : value2 } */
boolean as_map; boolean as_map;
/** Number of enumerated values whose texts are changed. */
size_t nof_enum_texts;
/** List of enumerated values whose texts are changed. */
const JsonEnumText* enum_texts;
}; };
/** This macro makes sure that coding errors will only be displayed if the silent /** This macro makes sure that coding errors will only be displayed if the silent
......
...@@ -5963,7 +5963,7 @@ int Record_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& ...@@ -5963,7 +5963,7 @@ int Record_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
return get_at(0)->JSON_encode(*fld_descr(0), p_tok); return get_at(0)->JSON_encode(*fld_descr(0), p_tok);
} }
if (p_td.json->as_map) { // TODO: implement negtest if (p_td.json->as_map) {
const UNIVERSAL_CHARSTRING* key_ustr = dynamic_cast< const UNIVERSAL_CHARSTRING* key_ustr = dynamic_cast<
const UNIVERSAL_CHARSTRING*>(get_at(0)); const UNIVERSAL_CHARSTRING*>(get_at(0));
if (NULL == key_ustr) { if (NULL == key_ustr) {
...@@ -6016,8 +6016,9 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr, ...@@ -6016,8 +6016,9 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
} }
boolean as_value = NULL != p_td.json && p_td.json->as_value; boolean as_value = NULL != p_td.json && p_td.json->as_value;
boolean as_map = NULL != p_td.json && p_td.json->as_map;
int enc_len = as_value ? 0 : p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL); int enc_len = (as_value || as_map) ? 0 : p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
int values_idx = 0; int values_idx = 0;
int edescr_idx = 0; int edescr_idx = 0;
...@@ -6031,7 +6032,7 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr, ...@@ -6031,7 +6032,7 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(i, values_idx); 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); const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(i, edescr_idx);
if (!as_value && NULL != err_vals && NULL != err_vals->before) { if (!as_value && !as_map && NULL != err_vals && NULL != err_vals->before) {
if (NULL == err_vals->before->errval) { if (NULL == err_vals->before->errval) {
TTCN_error("internal error: erroneous before value missing"); TTCN_error("internal error: erroneous before value missing");
} }
...@@ -6057,27 +6058,56 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr, ...@@ -6057,27 +6058,56 @@ int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
if (NULL == err_vals->value->type_descr) { if (NULL == err_vals->value->type_descr) {
TTCN_error("internal error: erroneous before typedescriptor missing"); TTCN_error("internal error: erroneous before typedescriptor missing");
}