From 70f345012d2da2bb67abcc8f84ef7e97b7759293 Mon Sep 17 00:00:00 2001 From: vglavnyy <31897320+vglavnyy@users.noreply.github.com> Date: Fri, 5 Jan 2018 01:12:18 +0700 Subject: [PATCH] GenerateText generate a text string for default identifier of enum and float scalar. An enum identifier printed as the strictly quoted string. (#4527) --- src/idl_gen_text.cpp | 66 ++++++++++++++++++++++--------------------- tests/monsterdata_test.golden | 4 +-- tests/test.cpp | 33 ++++++++++++++++++++++ 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/idl_gen_text.cpp b/src/idl_gen_text.cpp index 89a1810..95165fd 100644 --- a/src/idl_gen_text.cpp +++ b/src/idl_gen_text.cpp @@ -53,7 +53,9 @@ bool Print(T val, Type type, int /*indent*/, Type * /*union_type*/, if (type.enum_def && opts.output_enum_identifiers) { auto enum_val = type.enum_def->ReverseLookup(static_cast(val)); if (enum_val) { - OutputIdentifier(enum_val->name, opts, _text); + text += "\""; + text += enum_val->name; + text += "\""; return true; } } @@ -147,13 +149,18 @@ bool Print(const void *val, Type type, int indent, } // Generate text for a scalar field. -template -static bool GenField(const FieldDef &fd, const Table *table, bool fixed, - const IDLOptions &opts, int indent, std::string *_text) { - return Print(fixed ? reinterpret_cast(table)->GetField( - fd.value.offset) - : table->GetField(fd.value.offset, 0), - fd.value.type, indent, nullptr, opts, _text); +template static bool GenField(const FieldDef &fd, + const Table *table, bool fixed, + const IDLOptions &opts, + int indent, + std::string *_text) { + return Print(fixed ? + reinterpret_cast(table)->GetField(fd.value.offset) : + table->GetField(fd.value.offset, + IsFloat(fd.value.type.base_type) ? + static_cast(strtod(fd.value.constant.c_str(), nullptr)) : + static_cast(StringToInt(fd.value.constant.c_str()))), + fd.value.type, indent, nullptr, opts, _text); } 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)) text += ":"; text += " "; - if (is_present) { - switch (fd.value.type.base_type) { + switch (fd.value.type.base_type) { // clang-format off #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ @@ -223,29 +229,25 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, return false; \ } \ break; - FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD - // Generate drop-thru case statements for all pointer types: - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ - case BASE_TYPE_ ## ENUM: - FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD - if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts), - union_type, opts, _text)) { - return false; - } - break; + FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD + // Generate drop-thru case statements for all pointer types: + #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ + CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + case BASE_TYPE_ ## ENUM: + FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD + if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts), + union_type, opts, _text)) { + return false; + } + break; // clang-format on - } - if (fd.value.type.base_type == BASE_TYPE_UTYPE) { - auto enum_val = fd.value.type.enum_def->ReverseLookup( - table->GetField(fd.value.offset, 0)); - assert(enum_val); - union_type = &enum_val->union_type; - } - } else { - text += fd.value.constant; + } + if (fd.value.type.base_type == BASE_TYPE_UTYPE) { + auto enum_val = fd.value.type.enum_def->ReverseLookup( + table->GetField(fd.value.offset, 0)); + union_type = enum_val ? &enum_val->union_type : nullptr; } } } diff --git a/tests/monsterdata_test.golden b/tests/monsterdata_test.golden index e6304b5..fe55a87 100644 --- a/tests/monsterdata_test.golden +++ b/tests/monsterdata_test.golden @@ -4,7 +4,7 @@ y: 2.0, z: 3.0, test1: 3.0, - test2: Green, + test2: "Green", test3: { a: 10, b: 20 @@ -24,7 +24,7 @@ 8, 9 ], - test_type: Monster, + test_type: "Monster", test: { name: "Fred" }, diff --git a/tests/test.cpp b/tests/test.cpp index 56d96c2..3b7e3d5 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -541,6 +541,37 @@ void TriviallyCopyableTest() { // 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 // text back from it: void ParseAndGenerateTextTest() { @@ -1936,6 +1967,8 @@ int main(int /*argc*/, const char * /*argv*/ []) { TypeAliasesTest(); EndianSwapTest(); + JsonDefaultTest(); + FlexBuffersTest(); if (!testing_fails) { -- 2.7.4