Commit 70f34501 authored by vglavnyy's avatar vglavnyy Committed by Wouter van Oortmerssen

GenerateText generate a text string for default identifier of enum and float…

GenerateText generate a text string for default identifier of enum and float scalar. An enum identifier printed as the strictly quoted string. (#4527)
parent a056402f
...@@ -53,7 +53,9 @@ bool Print(T val, Type type, int /*indent*/, Type * /*union_type*/, ...@@ -53,7 +53,9 @@ bool Print(T val, Type type, int /*indent*/, Type * /*union_type*/,
if (type.enum_def && opts.output_enum_identifiers) { if (type.enum_def && opts.output_enum_identifiers) {
auto enum_val = type.enum_def->ReverseLookup(static_cast<int>(val)); auto enum_val = type.enum_def->ReverseLookup(static_cast<int>(val));
if (enum_val) { if (enum_val) {
OutputIdentifier(enum_val->name, opts, _text); text += "\"";
text += enum_val->name;
text += "\"";
return true; return true;
} }
} }
...@@ -147,13 +149,18 @@ bool Print<const void *>(const void *val, Type type, int indent, ...@@ -147,13 +149,18 @@ bool Print<const void *>(const void *val, Type type, int indent,
} }
// Generate text for a scalar field. // Generate text for a scalar field.
template<typename T> template<typename T> static bool GenField(const FieldDef &fd,
static bool GenField(const FieldDef &fd, const Table *table, bool fixed, const Table *table, bool fixed,
const IDLOptions &opts, int indent, std::string *_text) { const IDLOptions &opts,
return Print(fixed ? reinterpret_cast<const Struct *>(table)->GetField<T>( int indent,
fd.value.offset) std::string *_text) {
: table->GetField<T>(fd.value.offset, 0), return Print(fixed ?
fd.value.type, indent, nullptr, opts, _text); reinterpret_cast<const Struct *>(table)->GetField<T>(fd.value.offset) :
table->GetField<T>(fd.value.offset,
IsFloat(fd.value.type.base_type) ?
static_cast<T>(strtod(fd.value.constant.c_str(), nullptr)) :
static_cast<T>(StringToInt(fd.value.constant.c_str()))),
fd.value.type, indent, nullptr, opts, _text);
} }
static bool GenStruct(const StructDef &struct_def, const Table *table, static bool GenStruct(const StructDef &struct_def, const Table *table,
...@@ -212,8 +219,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, ...@@ -212,8 +219,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
fd.value.type.base_type != BASE_TYPE_VECTOR)) fd.value.type.base_type != BASE_TYPE_VECTOR))
text += ":"; text += ":";
text += " "; text += " ";
if (is_present) { switch (fd.value.type.base_type) {
switch (fd.value.type.base_type) {
// clang-format off // clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
...@@ -223,29 +229,25 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, ...@@ -223,29 +229,25 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
return false; \ return false; \
} \ } \
break; break;
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD #undef FLATBUFFERS_TD
// Generate drop-thru case statements for all pointer types: // Generate drop-thru case statements for all pointer types:
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
case BASE_TYPE_ ## ENUM: case BASE_TYPE_ ## ENUM:
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD #undef FLATBUFFERS_TD
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts), if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
union_type, opts, _text)) { union_type, opts, _text)) {
return false; return false;
} }
break; break;
// clang-format on // clang-format on
} }
if (fd.value.type.base_type == BASE_TYPE_UTYPE) { if (fd.value.type.base_type == BASE_TYPE_UTYPE) {
auto enum_val = fd.value.type.enum_def->ReverseLookup( auto enum_val = fd.value.type.enum_def->ReverseLookup(
table->GetField<uint8_t>(fd.value.offset, 0)); table->GetField<uint8_t>(fd.value.offset, 0));
assert(enum_val); union_type = enum_val ? &enum_val->union_type : nullptr;
union_type = &enum_val->union_type;
}
} else {
text += fd.value.constant;
} }
} }
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
y: 2.0, y: 2.0,
z: 3.0, z: 3.0,
test1: 3.0, test1: 3.0,
test2: Green, test2: "Green",
test3: { test3: {
a: 10, a: 10,
b: 20 b: 20
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
8, 8,
9 9
], ],
test_type: Monster, test_type: "Monster",
test: { test: {
name: "Fred" name: "Fred"
}, },
......
...@@ -541,6 +541,37 @@ void TriviallyCopyableTest() { ...@@ -541,6 +541,37 @@ void TriviallyCopyableTest() {
// clang-format on // clang-format on
} }
// Check stringify of an default enum value to json
void JsonDefaultTest() {
// load FlatBuffer schema (.fbs) from disk
std::string schemafile;
TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_test.fbs").c_str(),
false, &schemafile), true);
// parse schema first, so we can use it to parse the data after
flatbuffers::Parser parser;
auto include_test_path =
flatbuffers::ConCatPathFileName(test_data_path, "include_test");
const char *include_directories[] = { test_data_path.c_str(),
include_test_path.c_str(), nullptr };
TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
// create incomplete monster and store to json
parser.opts.output_default_scalars_in_json = true;
parser.opts.output_enum_identifiers = true;
flatbuffers::FlatBufferBuilder builder;
auto name = builder.CreateString("default_enum");
MonsterBuilder color_monster(builder);
color_monster.add_name(name);
FinishMonsterBuffer(builder, color_monster.Finish());
std::string jsongen;
auto result = GenerateText(parser, builder.GetBufferPointer(), &jsongen);
TEST_EQ(result, true);
// default value of the "color" field is Blue
TEST_EQ(std::string::npos != jsongen.find("color: \"Blue\""), true);
// default value of the "testf" field is 3.14159
TEST_EQ(std::string::npos != jsongen.find("testf: 3.14159"), true);
}
// example of parsing text straight into a buffer, and generating // example of parsing text straight into a buffer, and generating
// text back from it: // text back from it:
void ParseAndGenerateTextTest() { void ParseAndGenerateTextTest() {
...@@ -1936,6 +1967,8 @@ int main(int /*argc*/, const char * /*argv*/ []) { ...@@ -1936,6 +1967,8 @@ int main(int /*argc*/, const char * /*argv*/ []) {
TypeAliasesTest(); TypeAliasesTest();
EndianSwapTest(); EndianSwapTest();
JsonDefaultTest();
FlexBuffersTest(); FlexBuffersTest();
if (!testing_fails) { if (!testing_fails) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment