Merge branch 'master' into master

This commit is contained in:
jviel-beta
2023-06-19 11:20:48 -04:00
committed by GitHub
399 changed files with 15038 additions and 4764 deletions
+28 -7
View File
@@ -16,20 +16,38 @@ filegroup(
visibility = ["//visibility:public"],
)
cc_library(
name = "code_generators",
srcs = ["code_generators.cpp"],
hdrs = [
"//:public_headers",
],
strip_include_prefix = "/include",
visibility = ["//:__subpackages__"],
)
cc_library(
name = "generate_fbs",
srcs = ["idl_gen_fbs.cpp"],
hdrs = ["idl_gen_fbs.h"],
strip_include_prefix = "/src",
visibility = ["//:__subpackages__"],
deps = [":code_generators"],
)
# Public flatc library to compile flatbuffer files at runtime.
cc_library(
name = "flatbuffers",
srcs = [
"code_generators.cpp",
"idl_gen_fbs.cpp",
"idl_gen_fbs.h",
"idl_gen_text.cpp",
"idl_gen_text.h",
"idl_parser.cpp",
"reflection.cpp",
"util.cpp",
],
hdrs = ["//:public_headers"],
hdrs = [
"//:public_headers",
],
linkopts = select({
# TODO: Bazel uses `clang` instead of `clang++` to link
# C++ code on BSD. Temporarily adding these linker flags while
@@ -40,7 +58,11 @@ cc_library(
"//conditions:default": [],
}),
strip_include_prefix = "/include",
visibility = ["//:__pkg__"],
visibility = ["//:__subpackages__"],
deps = [
":code_generators",
":generate_fbs",
],
)
# Public flatc compiler library.
@@ -101,10 +123,9 @@ cc_library(
"idl_gen_json_schema.h",
"idl_gen_kotlin.cpp",
"idl_gen_kotlin.h",
"idl_gen_kotlin_kmp.cpp",
"idl_gen_lobster.cpp",
"idl_gen_lobster.h",
"idl_gen_lua.cpp",
"idl_gen_lua.h",
"idl_gen_php.cpp",
"idl_gen_php.h",
"idl_gen_python.cpp",
+10 -2
View File
@@ -1,6 +1,7 @@
#include "annotated_binary_text_gen.h"
#include <algorithm>
#include <cstdint>
#include <fstream>
#include <ostream>
#include <sstream>
@@ -36,6 +37,7 @@ static std::string ToString(const BinarySectionType type) {
case BinarySectionType::Struct: return "struct";
case BinarySectionType::String: return "string";
case BinarySectionType::Vector: return "vector";
case BinarySectionType::Vector64: return "vector64";
case BinarySectionType::Unknown: return "unknown";
case BinarySectionType::Union: return "union";
case BinarySectionType::Padding: return "padding";
@@ -44,7 +46,9 @@ static std::string ToString(const BinarySectionType type) {
}
static bool IsOffset(const BinaryRegionType type) {
return type == BinaryRegionType::UOffset || type == BinaryRegionType::SOffset;
return type == BinaryRegionType::UOffset ||
type == BinaryRegionType::SOffset ||
type == BinaryRegionType::UOffset64;
}
template<typename T> std::string ToString(T value) {
@@ -119,6 +123,9 @@ static std::string ToValueString(const BinaryRegion &region,
case BinaryRegionType::UType: return ToValueString<uint8_t>(region, binary);
// Handle Offsets separately, incase they add additional details.
case BinaryRegionType::UOffset64:
s += ToValueString<uint64_t>(region, binary);
break;
case BinaryRegionType::UOffset:
s += ToValueString<uint32_t>(region, binary);
break;
@@ -368,7 +375,8 @@ static void GenerateSection(std::ostream &os, const BinarySection &section,
// As a space saving measure, skip generating every vector element, just put
// the first and last elements in the output. Skip the whole thing if there
// are only three or fewer elements, as it doesn't save space.
if (section.type == BinarySectionType::Vector &&
if ((section.type == BinarySectionType::Vector ||
section.type == BinarySectionType::Vector64) &&
!output_config.include_vector_contents && section.regions.size() > 4) {
// Generate the length region which should be first.
GenerateRegion(os, section.regions[0], section, binary, output_config);
+5 -5
View File
@@ -101,15 +101,15 @@ class BaseBfbsGenerator : public CodeGenerator {
virtual ~BaseBfbsGenerator() {}
BaseBfbsGenerator() : schema_(nullptr) {}
virtual Status GenerateFromSchema(
const reflection::Schema *schema) = 0;
virtual Status GenerateFromSchema(const reflection::Schema *schema,
const CodeGenOptions &options) = 0;
virtual uint64_t SupportedAdvancedFeatures() const = 0;
// Override of the Generator::GenerateCode method that does the initial
// deserialization and verification steps.
Status GenerateCode(const uint8_t *buffer,
int64_t length) FLATBUFFERS_OVERRIDE {
Status GenerateCode(const uint8_t *buffer, int64_t length,
const CodeGenOptions &options) FLATBUFFERS_OVERRIDE {
flatbuffers::Verifier verifier(buffer, static_cast<size_t>(length));
if (!reflection::VerifySchemaBuffer(verifier)) {
return FAILED_VERIFICATION;
@@ -124,7 +124,7 @@ class BaseBfbsGenerator : public CodeGenerator {
return FAILED_VERIFICATION;
}
Status status = GenerateFromSchema(schema_);
Status status = GenerateFromSchema(schema_, options);
schema_ = nullptr;
return status;
}
+12 -6
View File
@@ -28,6 +28,7 @@
#include "bfbs_namer.h"
// The intermediate representation schema.
#include "flatbuffers/code_generator.h"
#include "flatbuffers/reflection.h"
#include "flatbuffers/reflection_generated.h"
@@ -78,7 +79,10 @@ class LuaBfbsGenerator : public BaseBfbsGenerator {
flatc_version_(flatc_version),
namer_(LuaDefaultConfig(), LuaKeywords()) {}
Status GenerateFromSchema(const r::Schema *schema) FLATBUFFERS_OVERRIDE {
Status GenerateFromSchema(const r::Schema *schema,
const CodeGenOptions &options)
FLATBUFFERS_OVERRIDE {
options_ = options;
if (!GenerateEnums(schema->enums())) { return ERROR; }
if (!GenerateObjects(schema->objects(), schema->root_table())) {
return ERROR;
@@ -88,10 +92,9 @@ class LuaBfbsGenerator : public BaseBfbsGenerator {
using BaseBfbsGenerator::GenerateCode;
Status GenerateCode(const Parser &parser, const std::string &path,
const std::string &filename) FLATBUFFERS_OVERRIDE {
if (!GenerateLua(parser, path, filename)) { return ERROR; }
return OK;
Status GenerateCode(const Parser &, const std::string &,
const std::string &) override {
return Status::NOT_IMPLEMENTED;
}
Status GenerateMakeRule(const Parser &parser, const std::string &path,
@@ -653,12 +656,15 @@ class LuaBfbsGenerator : public BaseBfbsGenerator {
// TODO(derekbailey): figure out a save file without depending on util.h
EnsureDirExists(path);
const std::string file_name = path + "/" + namer_.File(name);
const std::string file_name =
options_.output_path + path + "/" + namer_.File(name);
SaveFile(file_name.c_str(), code, false);
}
std::unordered_set<std::string> keywords_;
std::map<std::string, std::string> requires_;
CodeGenOptions options_;
const r::Object *current_obj_;
const r::Enum *current_enum_;
const std::string flatc_version_;
+9 -2
View File
@@ -28,6 +28,7 @@
#include "bfbs_namer.h"
// The intermediate representation schema.
#include "flatbuffers/code_generator.h"
#include "flatbuffers/reflection.h"
#include "flatbuffers/reflection_generated.h"
@@ -95,7 +96,10 @@ class NimBfbsGenerator : public BaseBfbsGenerator {
flatc_version_(flatc_version),
namer_(NimDefaultConfig(), NimKeywords()) {}
Status GenerateFromSchema(const r::Schema *schema) FLATBUFFERS_OVERRIDE {
Status GenerateFromSchema(const r::Schema *schema,
const CodeGenOptions &options)
FLATBUFFERS_OVERRIDE {
options_ = options;
ForAllEnums(schema->enums(), [&](const r::Enum *enum_def) {
StartCodeBlock(enum_def);
GenerateEnum(enum_def);
@@ -671,12 +675,15 @@ class NimBfbsGenerator : public BaseBfbsGenerator {
// TODO(derekbailey): figure out a save file without depending on util.h
EnsureDirExists(path);
const std::string file_name = path + "/" + namer_.File(name);
const std::string file_name =
options_.output_path + path + "/" + namer_.File(name);
SaveFile(file_name.c_str(), code, false);
}
std::unordered_set<std::string> keywords_;
std::map<std::string, std::string> imports_;
CodeGenOptions options_;
const r::Object *current_obj_;
const r::Enum *current_enum_;
const std::string flatc_version_;
+119 -44
View File
@@ -1,10 +1,13 @@
#include "binary_annotator.h"
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <limits>
#include <string>
#include <vector>
#include "flatbuffers/base.h"
#include "flatbuffers/reflection.h"
#include "flatbuffers/util.h"
#include "flatbuffers/verifier.h"
@@ -26,7 +29,7 @@ static BinaryRegion MakeBinaryRegion(
const uint64_t offset = 0, const uint64_t length = 0,
const BinaryRegionType type = BinaryRegionType::Unknown,
const uint64_t array_length = 0, const uint64_t points_to_offset = 0,
const BinaryRegionComment comment = {}) {
BinaryRegionComment comment = {}) {
BinaryRegion region;
region.offset = offset;
region.length = length;
@@ -37,9 +40,9 @@ static BinaryRegion MakeBinaryRegion(
return region;
}
static BinarySection MakeBinarySection(
const std::string &name, const BinarySectionType type,
const std::vector<BinaryRegion> regions) {
static BinarySection MakeBinarySection(const std::string &name,
const BinarySectionType type,
std::vector<BinaryRegion> regions) {
BinarySection section;
section.name = name;
section.type = type;
@@ -118,12 +121,15 @@ static BinarySection GenerateMissingSection(const uint64_t offset,
std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_));
if (!reflection::VerifySchemaBuffer(verifier)) { return {}; }
if ((is_size_prefixed_ &&
!reflection::VerifySizePrefixedSchemaBuffer(verifier)) ||
!reflection::VerifySchemaBuffer(verifier)) {
return {};
}
// The binary is too short to read as a flatbuffers.
// TODO(dbaileychess): We could spit out the annotated buffer sections, but
// I'm not sure if it is worth it.
if (binary_length_ < 4) { return {}; }
if (binary_length_ < FLATBUFFERS_MIN_BUFFER_SIZE) { return {}; }
// Make sure we start with a clean slate.
vtables_.clear();
@@ -151,7 +157,41 @@ std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
}
uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
const auto root_table_offset = ReadScalar<uint32_t>(header_offset);
uint64_t offset = header_offset;
std::vector<BinaryRegion> regions;
// If this binary is a size prefixed one, attempt to parse the size.
if (is_size_prefixed_) {
BinaryRegionComment prefix_length_comment;
prefix_length_comment.type = BinaryRegionCommentType::SizePrefix;
bool has_prefix_value = false;
const auto prefix_length = ReadScalar<uoffset64_t>(offset);
if (*prefix_length <= binary_length_) {
regions.push_back(MakeBinaryRegion(offset, sizeof(uoffset64_t),
BinaryRegionType::Uint64, 0, 0,
prefix_length_comment));
offset += sizeof(uoffset64_t);
has_prefix_value = true;
}
if (!has_prefix_value) {
const auto prefix_length = ReadScalar<uoffset_t>(offset);
if (*prefix_length <= binary_length_) {
regions.push_back(MakeBinaryRegion(offset, sizeof(uoffset_t),
BinaryRegionType::Uint32, 0, 0,
prefix_length_comment));
offset += sizeof(uoffset_t);
has_prefix_value = true;
}
}
if (!has_prefix_value) {
SetError(prefix_length_comment, BinaryRegionStatus::ERROR);
}
}
const auto root_table_offset = ReadScalar<uint32_t>(offset);
if (!root_table_offset.has_value()) {
// This shouldn't occur, since we validate the min size of the buffer
@@ -159,22 +199,20 @@ uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
return std::numeric_limits<uint64_t>::max();
}
std::vector<BinaryRegion> regions;
uint64_t offset = header_offset;
// TODO(dbaileychess): sized prefixed value
const auto root_table_loc = offset + *root_table_offset;
BinaryRegionComment root_offset_comment;
root_offset_comment.type = BinaryRegionCommentType::RootTableOffset;
root_offset_comment.name = schema_->root_table()->name()->str();
if (!IsValidOffset(root_table_offset.value())) {
if (!IsValidOffset(root_table_loc)) {
SetError(root_offset_comment,
BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
}
regions.push_back(
MakeBinaryRegion(offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
root_table_offset.value(), root_offset_comment));
regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
BinaryRegionType::UOffset, 0,
root_table_loc, root_offset_comment));
offset += sizeof(uint32_t);
if (IsValidRead(offset, flatbuffers::kFileIdentifierLength) &&
@@ -193,7 +231,7 @@ uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
AddSection(header_offset, MakeBinarySection("", BinarySectionType::Header,
std::move(regions)));
return root_table_offset.value();
return root_table_loc;
}
BinaryAnnotator::VTable *BinaryAnnotator::GetOrBuildVTable(
@@ -656,7 +694,18 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
}
// Read the offset
const auto offset_from_field = ReadScalar<uint32_t>(field_offset);
uint64_t offset = 0;
uint64_t length = sizeof(uint32_t);
BinaryRegionType region_type = BinaryRegionType::UOffset;
if (field->offset64()) {
length = sizeof(uint64_t);
region_type = BinaryRegionType::UOffset64;
offset = ReadScalar<uint64_t>(field_offset).value_or(0);
} else {
offset = ReadScalar<uint32_t>(field_offset).value_or(0);
}
// const auto offset_from_field = ReadScalar<uint32_t>(field_offset);
uint64_t offset_of_next_item = 0;
BinaryRegionComment offset_field_comment;
offset_field_comment.type = BinaryRegionCommentType::TableOffsetField;
@@ -666,7 +715,7 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
// Validate any field that isn't inline (i.e., non-structs).
if (!IsInlineField(field)) {
if (!offset_from_field.has_value()) {
if (offset == 0) {
const uint64_t remaining = RemainingBytes(field_offset);
SetError(offset_field_comment,
@@ -678,14 +727,14 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
continue;
}
offset_of_next_item = field_offset + offset_from_field.value();
offset_of_next_item = field_offset + offset;
if (!IsValidOffset(offset_of_next_item)) {
SetError(offset_field_comment,
BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
regions.push_back(MakeBinaryRegion(
field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
offset_of_next_item, offset_field_comment));
regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
offset_of_next_item,
offset_field_comment));
continue;
}
}
@@ -702,9 +751,9 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
} else {
offset_field_comment.default_value = "(table)";
regions.push_back(MakeBinaryRegion(
field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
offset_of_next_item, offset_field_comment));
regions.push_back(MakeBinaryRegion(field_offset, length, region_type,
0, offset_of_next_item,
offset_field_comment));
BuildTable(offset_of_next_item, BinarySectionType::Table,
next_object);
@@ -713,17 +762,25 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
case reflection::BaseType::String: {
offset_field_comment.default_value = "(string)";
regions.push_back(MakeBinaryRegion(
field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
offset_of_next_item, offset_field_comment));
regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
offset_of_next_item,
offset_field_comment));
BuildString(offset_of_next_item, table, field);
} break;
case reflection::BaseType::Vector: {
offset_field_comment.default_value = "(vector)";
regions.push_back(MakeBinaryRegion(
field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
offset_of_next_item, offset_field_comment));
regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
offset_of_next_item,
offset_field_comment));
BuildVector(offset_of_next_item, table, field, table_offset,
vtable->fields);
} break;
case reflection::BaseType::Vector64: {
offset_field_comment.default_value = "(vector64)";
regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
offset_of_next_item,
offset_field_comment));
BuildVector(offset_of_next_item, table, field, table_offset,
vtable->fields);
} break;
@@ -768,8 +825,7 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
offset_field_comment.default_value =
"(union of type `" + enum_type + "`)";
regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint32_t),
BinaryRegionType::UOffset, 0,
regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
union_offset, offset_field_comment));
} break;
@@ -986,7 +1042,28 @@ void BinaryAnnotator::BuildVector(
BinaryRegionComment vector_length_comment;
vector_length_comment.type = BinaryRegionCommentType::VectorLength;
const auto vector_length = ReadScalar<uint32_t>(vector_offset);
const bool is_64_bit_vector =
field->type()->base_type() == reflection::BaseType::Vector64;
flatbuffers::Optional<uint64_t> vector_length;
uint32_t vector_length_size_type = 0;
BinaryRegionType region_type = BinaryRegionType::Uint32;
BinarySectionType section_type = BinarySectionType::Vector;
if (is_64_bit_vector) {
auto v = ReadScalar<uint64_t>(vector_offset);
if (v.has_value()) { vector_length = v.value(); }
vector_length_size_type = sizeof(uint64_t);
region_type = BinaryRegionType::Uint64;
section_type = BinarySectionType::Vector64;
} else {
auto v = ReadScalar<uint32_t>(vector_offset);
if (v.has_value()) { vector_length = v.value(); }
vector_length_size_type = sizeof(uint32_t);
region_type = BinaryRegionType::Uint32;
section_type = BinarySectionType::Vector;
}
if (!vector_length.has_value()) {
const uint64_t remaining = RemainingBytes(vector_offset);
SetError(vector_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
@@ -1006,7 +1083,7 @@ void BinaryAnnotator::BuildVector(
// Validate there are enough bytes left in the binary to process all the
// items.
const uint64_t last_item_offset =
vector_offset + sizeof(uint32_t) +
vector_offset + vector_length_size_type +
vector_length.value() * GetElementSize(field);
if (!IsValidOffset(last_item_offset - 1)) {
@@ -1016,20 +1093,18 @@ void BinaryAnnotator::BuildVector(
MakeSingleRegionBinarySection(
std::string(table->name()->c_str()) + "." + field->name()->c_str(),
BinarySectionType::Vector,
MakeBinaryRegion(vector_offset, sizeof(uint32_t),
BinaryRegionType::Uint32, 0, 0,
vector_length_comment)));
MakeBinaryRegion(vector_offset, vector_length_size_type,
region_type, 0, 0, vector_length_comment)));
return;
}
std::vector<BinaryRegion> regions;
regions.push_back(MakeBinaryRegion(vector_offset, sizeof(uint32_t),
BinaryRegionType::Uint32, 0, 0,
vector_length_comment));
regions.push_back(MakeBinaryRegion(vector_offset, vector_length_size_type,
region_type, 0, 0, vector_length_comment));
// Consume the vector length offset.
uint64_t offset = vector_offset + sizeof(uint32_t);
uint64_t offset = vector_offset + vector_length_size_type;
switch (field->type()->element()) {
case reflection::BaseType::Obj: {
@@ -1302,7 +1377,7 @@ void BinaryAnnotator::BuildVector(
AddSection(vector_offset,
MakeBinarySection(std::string(table->name()->c_str()) + "." +
field->name()->c_str(),
BinarySectionType::Vector, std::move(regions)));
section_type, std::move(regions)));
}
std::string BinaryAnnotator::BuildUnion(const uint64_t union_offset,
+9 -3
View File
@@ -48,6 +48,7 @@ enum class BinaryRegionType {
Float = 15,
Double = 16,
UType = 17,
UOffset64 = 18,
};
template<typename T>
@@ -179,6 +180,7 @@ enum class BinarySectionType {
Vector = 7,
Union = 8,
Padding = 9,
Vector64 = 10,
};
// A section of the binary that is grouped together in some logical manner, and
@@ -216,6 +218,7 @@ inline static BinaryRegionType GetRegionType(reflection::BaseType base_type) {
inline static std::string ToString(const BinaryRegionType type) {
switch (type) {
case BinaryRegionType::UOffset: return "UOffset32";
case BinaryRegionType::UOffset64: return "UOffset64";
case BinaryRegionType::SOffset: return "SOffset32";
case BinaryRegionType::VOffset: return "VOffset16";
case BinaryRegionType::Bool: return "bool";
@@ -242,12 +245,14 @@ class BinaryAnnotator {
explicit BinaryAnnotator(const uint8_t *const bfbs,
const uint64_t bfbs_length,
const uint8_t *const binary,
const uint64_t binary_length)
const uint64_t binary_length,
const bool is_size_prefixed)
: bfbs_(bfbs),
bfbs_length_(bfbs_length),
schema_(reflection::GetSchema(bfbs)),
binary_(binary),
binary_length_(binary_length) {}
binary_length_(binary_length),
is_size_prefixed_(is_size_prefixed) {}
std::map<uint64_t, BinarySection> Annotate();
@@ -258,7 +263,7 @@ class BinaryAnnotator {
uint16_t offset_from_table = 0;
};
const reflection::Object *referring_table;
const reflection::Object *referring_table = nullptr;
// Field ID -> {field def, offset from table}
std::map<uint16_t, Entry> fields;
@@ -387,6 +392,7 @@ class BinaryAnnotator {
// The binary data itself.
const uint8_t *binary_;
const uint64_t binary_length_;
const bool is_size_prefixed_;
// Map of binary offset to vtables, to dedupe vtables.
std::map<uint64_t, std::list<VTable>> vtables_;
+1 -57
View File
@@ -30,9 +30,7 @@
namespace flatbuffers {
namespace {
static std::string JavaCSharpMakeRule(const bool java, const Parser &parser,
std::string JavaCSharpMakeRule(const bool java, const Parser &parser,
const std::string &path,
const std::string &file_name) {
const std::string file_extension = java ? ".java" : ".cs";
@@ -64,18 +62,6 @@ static std::string JavaCSharpMakeRule(const bool java, const Parser &parser,
return make_rule;
}
static std::string BinaryFileName(const Parser &parser, const std::string &path,
const std::string &file_name) {
auto ext = parser.file_extension_.length() ? parser.file_extension_ : "bin";
return path + file_name + "." + ext;
}
} // namespace
void CodeWriter::operator+=(std::string text) {
if (!ignore_ident_ && !text.empty()) AppendIdent(stream_);
@@ -346,48 +332,6 @@ std::string SimpleFloatConstantGenerator::NaN(float v) const {
return this->NaN(static_cast<double>(v));
}
std::string JavaMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
return JavaCSharpMakeRule(true, parser, path, file_name);
}
std::string CSharpMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
return JavaCSharpMakeRule(false, parser, path, file_name);
}
bool GenerateBinary(const Parser &parser, const std::string &path,
const std::string &file_name) {
if (parser.opts.use_flexbuffers) {
auto data_vec = parser.flex_builder_.GetBuffer();
auto data_ptr = reinterpret_cast<char *>(data(data_vec));
return !parser.flex_builder_.GetSize() ||
flatbuffers::SaveFile(
BinaryFileName(parser, path, file_name).c_str(), data_ptr,
parser.flex_builder_.GetSize(), true);
}
return !parser.builder_.GetSize() ||
flatbuffers::SaveFile(
BinaryFileName(parser, path, file_name).c_str(),
reinterpret_cast<char *>(parser.builder_.GetBufferPointer()),
parser.builder_.GetSize(), true);
}
std::string BinaryMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
if (!parser.builder_.GetSize()) return "";
std::string filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
std::string make_rule =
BinaryFileName(parser, path, filebase) + ": " + file_name;
auto included_files =
parser.GetIncludedFilesRecursive(parser.root_struct_def_->file);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
make_rule += " " + *it;
}
return make_rule;
}
} // namespace flatbuffers
#if defined(_MSC_VER)
+2 -2
View File
@@ -37,8 +37,8 @@ class FileNameSavingFileManager : public FileManager {
}
bool Loadfile(const std::string &absolute_file_name, std::string *content) {
(void) absolute_file_name;
(void) content;
(void)absolute_file_name;
(void)content;
return false;
}
+15 -10
View File
@@ -252,10 +252,9 @@ const static FlatCOption flatc_options[] = {
"Currently this is required to generate private types in Rust" },
{ "", "python-no-type-prefix-suffix", "",
"Skip emission of Python functions that are prefixed with typenames" },
{ "", "python-typing", "",
"Generate Python type annotations" },
{ "", "python-typing", "", "Generate Python type annotations" },
{ "", "file-names-only", "",
"Print out generated file names without writing to the files"},
"Print out generated file names without writing to the files" },
};
auto cmp = [](FlatCOption a, FlatCOption b) { return a.long_opt < b.long_opt; };
@@ -394,9 +393,11 @@ void FlatCompiler::AnnotateBinaries(const uint8_t *binary_schema,
const uint8_t *binary =
reinterpret_cast<const uint8_t *>(binary_contents.c_str());
const size_t binary_size = binary_contents.size();
const bool is_size_prefixed = options.opts.size_prefixed;
flatbuffers::BinaryAnnotator binary_annotator(
binary_schema, binary_schema_size, binary, binary_size);
binary_schema, binary_schema_size, binary, binary_size,
is_size_prefixed);
auto annotations = binary_annotator.Annotate();
@@ -663,7 +664,7 @@ FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc,
} else if (arg == "--annotate") {
if (++argi >= argc) Error("missing path following: " + arg, true);
options.annotate_schema = flatbuffers::PosixPath(argv[argi]);
} else if(arg == "--file-names-only") {
} else if (arg == "--file-names-only") {
// TODO (khhn): Provide 2 implementation
options.file_names_only = true;
} else {
@@ -865,11 +866,15 @@ std::unique_ptr<Parser> FlatCompiler::GenerateCode(const FlatCOptions &options,
// Prefer bfbs generators if present.
if (code_generator->SupportsBfbsGeneration()) {
const CodeGenerator::Status status =
code_generator->GenerateCode(bfbs_buffer, bfbs_length);
CodeGenOptions code_gen_options;
code_gen_options.output_path = options.output_path;
const CodeGenerator::Status status = code_generator->GenerateCode(
bfbs_buffer, bfbs_length, code_gen_options);
if (status != CodeGenerator::Status::OK) {
Error("Unable to generate " + code_generator->LanguageName() +
" for " + filebase + " using bfbs generator.");
" for " + filebase + code_generator->status_detail +
" using bfbs generator.");
}
} else {
if ((!code_generator->IsSchemaOnly() ||
@@ -878,7 +883,7 @@ std::unique_ptr<Parser> FlatCompiler::GenerateCode(const FlatCOptions &options,
filebase) !=
CodeGenerator::Status::OK) {
Error("Unable to generate " + code_generator->LanguageName() +
" for " + filebase);
" for " + filebase + code_generator->status_detail);
}
}
}
@@ -966,7 +971,7 @@ int FlatCompiler::Compile(const FlatCOptions &options) {
return 0;
}
if (options.generators.empty()) {
if (options.generators.empty() && options.conform_to_schema.empty()) {
Error("No generator registered");
return -1;
}
+5
View File
@@ -125,6 +125,11 @@ int main(int argc, const char *argv[]) {
"Generate Kotlin classes for tables/structs" },
flatbuffers::NewKotlinCodeGenerator());
flatc.RegisterCodeGenerator(
flatbuffers::FlatCOption{ "", "kotlin-kmp", "",
"Generate Kotlin multiplatform classes for tables/structs" },
flatbuffers::NewKotlinKMPCodeGenerator());
flatc.RegisterCodeGenerator(
flatbuffers::FlatCOption{ "", "lobster", "",
"Generate Lobster files for tables/structs" },
+40 -4
View File
@@ -31,9 +31,46 @@
#include "flatbuffers/util.h"
namespace flatbuffers {
namespace {
static std::string BinaryFileName(const Parser &parser, const std::string &path,
const std::string &file_name) {
auto ext = parser.file_extension_.length() ? parser.file_extension_ : "bin";
return path + file_name + "." + ext;
}
static bool GenerateBinary(const Parser &parser, const std::string &path,
const std::string &file_name) {
if (parser.opts.use_flexbuffers) {
auto data_vec = parser.flex_builder_.GetBuffer();
auto data_ptr = reinterpret_cast<char *>(data(data_vec));
return !parser.flex_builder_.GetSize() ||
flatbuffers::SaveFile(
BinaryFileName(parser, path, file_name).c_str(), data_ptr,
parser.flex_builder_.GetSize(), true);
}
return !parser.builder_.GetSize() ||
flatbuffers::SaveFile(
BinaryFileName(parser, path, file_name).c_str(),
reinterpret_cast<char *>(parser.builder_.GetBufferPointer()),
parser.builder_.GetSize(), true);
}
static std::string BinaryMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
if (!parser.builder_.GetSize()) return "";
std::string filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
std::string make_rule =
BinaryFileName(parser, path, filebase) + ": " + file_name;
auto included_files =
parser.GetIncludedFilesRecursive(parser.root_struct_def_->file);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
make_rule += " " + *it;
}
return make_rule;
}
class BinaryCodeGenerator : public CodeGenerator {
public:
Status GenerateCode(const Parser &parser, const std::string &path,
@@ -44,9 +81,8 @@ class BinaryCodeGenerator : public CodeGenerator {
// Generate code from the provided `buffer` of given `length`. The buffer is a
// serialized reflection.fbs.
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+287 -126
View File
@@ -22,6 +22,7 @@
#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include "flatbuffers/base.h"
#include "flatbuffers/code_generators.h"
@@ -76,8 +77,7 @@ static std::string GenIncludeGuard(const std::string &file_name,
static bool IsVectorOfPointers(const FieldDef &field) {
const auto &type = field.value.type;
const auto &vector_type = type.VectorType();
return type.base_type == BASE_TYPE_VECTOR &&
vector_type.base_type == BASE_TYPE_STRUCT &&
return IsVector(type) && vector_type.base_type == BASE_TYPE_STRUCT &&
!vector_type.struct_def->fixed && !field.native_inline;
}
@@ -106,6 +106,21 @@ struct IDLOptionsCpp : public IDLOptions {
: IDLOptions(opts), g_cpp_std(CPP_STD_11), g_only_fixed_enums(true) {}
};
// Iterates over all the fields of the object first by Offset type (Offset64
// before Offset32) and then by definition order.
static void ForAllFieldsOrderedByOffset(
const StructDef &object, std::function<void(const FieldDef *field)> func) {
// Loop over all the fields and call the func on all offset64 fields.
for (const FieldDef *field_def : object.fields.vec) {
if (field_def->offset64) { func(field_def); }
}
// Loop over all the fields a second time and call the func on all offset
// fields.
for (const FieldDef *field_def : object.fields.vec) {
if (!field_def->offset64) { func(field_def); }
}
}
class CppGenerator : public BaseGenerator {
public:
CppGenerator(const Parser &parser, const std::string &path,
@@ -272,6 +287,25 @@ class CppGenerator : public BaseGenerator {
}
}
void MarkIf64BitBuilderIsNeeded() {
if (needs_64_bit_builder_) { return; }
for (auto t : parser_.structs_.vec) {
if (t == nullptr) continue;
for (auto f : t->fields.vec) {
if (f == nullptr) continue;
if (f->offset64) {
needs_64_bit_builder_ = true;
break;
}
}
}
}
std::string GetBuilder() {
return std::string("::flatbuffers::FlatBufferBuilder") +
(needs_64_bit_builder_ ? "64" : "");
}
void GenExtraIncludes() {
for (const std::string &cpp_include : opts_.cpp_includes) {
code_ += "#include \"" + cpp_include + "\"";
@@ -279,6 +313,16 @@ class CppGenerator : public BaseGenerator {
if (!opts_.cpp_includes.empty()) { code_ += ""; }
}
void GenEmbeddedIncludes() {
if (parser_.opts.binary_schema_gen_embed && parser_.root_struct_def_) {
const std::string file_path =
GeneratedFileName(opts_.include_prefix, file_name_ + "_bfbs", opts_);
code_ += "// For access to the binary schema that produced this file.";
code_ += "#include \"" + file_path + "\"";
code_ += "";
}
}
std::string EscapeKeyword(const std::string &name) const {
return keywords_.find(name) == keywords_.end() ? name : name + "_";
}
@@ -333,10 +377,8 @@ class CppGenerator : public BaseGenerator {
code_ += "#pragma clang system_header\n\n";
}
code_ += "#include \"flatbuffers/flatbuffers.h\"";
code_ += "";
GenFlatbuffersVersionCheck();
code_ += "";
code_ += "#include <cstddef>";
code_ += "#include <cstdint>";
SetNameSpace(struct_def.defined_namespace);
auto name = Name(struct_def);
@@ -385,6 +427,9 @@ class CppGenerator : public BaseGenerator {
// Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file.
bool generate() {
// Check if we require a 64-bit flatbuffer builder.
MarkIf64BitBuilderIsNeeded();
code_.Clear();
code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
@@ -407,6 +452,7 @@ class CppGenerator : public BaseGenerator {
if (opts_.include_dependence_headers) { GenIncludeDependencies(); }
GenExtraIncludes();
GenEmbeddedIncludes();
FLATBUFFERS_ASSERT(!cur_name_space_);
@@ -518,6 +564,8 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("STRUCT_NAME", name);
code_.SetValue("CPP_NAME", cpp_name);
code_.SetValue("NULLABLE_EXT", NullableExtension());
code_.SetValue(
"SIZE_T", needs_64_bit_builder_ ? ",::flatbuffers::uoffset64_t" : "");
// The root datatype accessor:
code_ += "inline \\";
@@ -534,7 +582,8 @@ class CppGenerator : public BaseGenerator {
"*{{NULLABLE_EXT}}GetSizePrefixed{{STRUCT_NAME}}(const void "
"*buf) {";
code_ +=
" return ::flatbuffers::GetSizePrefixedRoot<{{CPP_NAME}}>(buf);";
" return "
"::flatbuffers::GetSizePrefixedRoot<{{CPP_NAME}}{{SIZE_T}}>(buf);";
code_ += "}";
code_ += "";
@@ -553,7 +602,8 @@ class CppGenerator : public BaseGenerator {
"*buf) {";
code_ +=
" return "
"::flatbuffers::GetMutableSizePrefixedRoot<{{CPP_NAME}}>(buf);";
"::flatbuffers::GetMutableSizePrefixedRoot<{{CPP_NAME}}{{SIZE_T}}>("
"buf);";
code_ += "}";
code_ += "";
}
@@ -600,7 +650,8 @@ class CppGenerator : public BaseGenerator {
code_ += "inline bool VerifySizePrefixed{{STRUCT_NAME}}Buffer(";
code_ += " ::flatbuffers::Verifier &verifier) {";
code_ +=
" return verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}>({{ID}});";
" return "
"verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}{{SIZE_T}}>({{ID}});";
code_ += "}";
code_ += "";
@@ -614,7 +665,7 @@ class CppGenerator : public BaseGenerator {
// Finish a buffer with a given root object:
code_ += "inline void Finish{{STRUCT_NAME}}Buffer(";
code_ += " ::flatbuffers::FlatBufferBuilder &fbb,";
code_ += " " + GetBuilder() + " &fbb,";
code_ += " ::flatbuffers::Offset<{{CPP_NAME}}> root) {";
if (parser_.file_identifier_.length())
code_ += " fbb.Finish(root, {{STRUCT_NAME}}Identifier());";
@@ -624,7 +675,7 @@ class CppGenerator : public BaseGenerator {
code_ += "";
code_ += "inline void FinishSizePrefixed{{STRUCT_NAME}}Buffer(";
code_ += " ::flatbuffers::FlatBufferBuilder &fbb,";
code_ += " " + GetBuilder() + " &fbb,";
code_ += " ::flatbuffers::Offset<{{CPP_NAME}}> root) {";
if (parser_.file_identifier_.length())
code_ += " fbb.FinishSizePrefixed(root, {{STRUCT_NAME}}Identifier());";
@@ -684,6 +735,7 @@ class CppGenerator : public BaseGenerator {
const IDLOptionsCpp opts_;
const TypedFloatConstantGenerator float_const_gen_;
bool needs_64_bit_builder_ = false;
const Namespace *CurrentNameSpace() const { return cur_name_space_; }
@@ -725,7 +777,12 @@ class CppGenerator : public BaseGenerator {
if (type.enum_def) return WrapInNameSpace(*type.enum_def);
if (type.base_type == BASE_TYPE_BOOL) return "bool";
}
return StringOf(type.base_type);
// Get real underlying type for union type
auto base_type = type.base_type;
if (type.base_type == BASE_TYPE_UTYPE && type.enum_def != nullptr) {
base_type = type.enum_def->underlying_type.base_type;
}
return StringOf(base_type);
}
// Return a C++ pointer type, specialized to the actual struct/table types,
@@ -735,10 +792,14 @@ class CppGenerator : public BaseGenerator {
case BASE_TYPE_STRING: {
return "::flatbuffers::String";
}
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeWire(
type.VectorType(), "", VectorElementUserFacing(type.VectorType()));
return "::flatbuffers::Vector<" + type_name + ">";
return "::flatbuffers::Vector" +
std::string((type.base_type == BASE_TYPE_VECTOR64) ? "64<"
: "<") +
type_name + ">";
}
case BASE_TYPE_STRUCT: {
return WrapInNameSpace(*type.struct_def);
@@ -754,13 +815,15 @@ class CppGenerator : public BaseGenerator {
// Return a C++ type for any type (scalar/pointer) specifically for
// building a flatbuffer.
std::string GenTypeWire(const Type &type, const char *postfix,
bool user_facing_type) const {
bool user_facing_type,
bool _64_bit_offset = false) const {
if (IsScalar(type.base_type)) {
return GenTypeBasic(type, user_facing_type) + postfix;
} else if (IsStruct(type)) {
return "const " + GenTypePointer(type) + " *";
} else {
return "::flatbuffers::Offset<" + GenTypePointer(type) + ">" + postfix;
return "::flatbuffers::Offset" + std::string(_64_bit_offset ? "64" : "") +
"<" + GenTypePointer(type) + ">" + postfix;
}
}
@@ -846,6 +909,7 @@ class CppGenerator : public BaseGenerator {
case BASE_TYPE_STRING: {
return NativeString(&field);
}
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeNative(type.VectorType(), true, field);
if (type.struct_def &&
@@ -854,8 +918,9 @@ class CppGenerator : public BaseGenerator {
type.struct_def->attributes.Lookup("native_custom_alloc");
return "std::vector<" + type_name + "," +
native_custom_alloc->constant + "<" + type_name + ">>";
} else
} else {
return "std::vector<" + type_name + ">";
}
}
case BASE_TYPE_STRUCT: {
auto type_name = WrapInNameSpace(*type.struct_def);
@@ -965,9 +1030,9 @@ class CppGenerator : public BaseGenerator {
std::string GetUnionElement(const EnumVal &ev, bool native_type,
const IDLOptions &opts) {
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
auto name = ev.union_type.struct_def->name;
std::string name = ev.union_type.struct_def->name;
if (native_type) {
name = NativeName(name, ev.union_type.struct_def, opts);
name = NativeName(std::move(name), ev.union_type.struct_def, opts);
}
return WrapInNameSpace(ev.union_type.struct_def->defined_namespace, name);
} else if (IsString(ev.union_type)) {
@@ -985,8 +1050,10 @@ class CppGenerator : public BaseGenerator {
}
std::string UnionVectorVerifySignature(const EnumDef &enum_def) {
auto name = Name(enum_def);
auto type = opts_.scoped_enums ? name : "uint8_t";
const std::string name = Name(enum_def);
const std::string &type =
opts_.scoped_enums ? name
: GenTypeBasic(enum_def.underlying_type, false);
return "bool Verify" + name + "Vector" +
"(::flatbuffers::Verifier &verifier, " +
"const ::flatbuffers::Vector<::flatbuffers::Offset<void>> "
@@ -1003,8 +1070,8 @@ class CppGenerator : public BaseGenerator {
std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) {
return "::flatbuffers::Offset<void> " +
(inclass ? "" : Name(enum_def) + "Union::") +
"Pack(::flatbuffers::FlatBufferBuilder &_fbb, " +
(inclass ? "" : Name(enum_def) + "Union::") + "Pack(" +
GetBuilder() + " &_fbb, " +
"const ::flatbuffers::rehasher_function_t *_rehasher" +
(inclass ? " = nullptr" : "") + ") const";
}
@@ -1012,8 +1079,7 @@ class CppGenerator : public BaseGenerator {
std::string TableCreateSignature(const StructDef &struct_def, bool predecl,
const IDLOptions &opts) {
return "::flatbuffers::Offset<" + Name(struct_def) + "> Create" +
Name(struct_def) +
"(::flatbuffers::FlatBufferBuilder &_fbb, const " +
Name(struct_def) + "(" + GetBuilder() + " &_fbb, const " +
NativeName(Name(struct_def), &struct_def, opts) +
" *_o, const ::flatbuffers::rehasher_function_t *_rehasher" +
(predecl ? " = nullptr" : "") + ")";
@@ -1023,7 +1089,7 @@ class CppGenerator : public BaseGenerator {
const IDLOptions &opts) {
return std::string(inclass ? "static " : "") + "::flatbuffers::Offset<" +
Name(struct_def) + "> " + (inclass ? "" : Name(struct_def) + "::") +
"Pack(::flatbuffers::FlatBufferBuilder &_fbb, " + "const " +
"Pack(" + GetBuilder() + " &_fbb, " + "const " +
NativeName(Name(struct_def), &struct_def, opts) + "* _o, " +
"const ::flatbuffers::rehasher_function_t *_rehasher" +
(inclass ? " = nullptr" : "") + ")";
@@ -1779,7 +1845,8 @@ class CppGenerator : public BaseGenerator {
if (IsStruct(vtype)) {
type = WrapInNameSpace(*vtype.struct_def);
} else {
type = GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
type = GenTypeWire(vtype, "", VectorElementUserFacing(vtype),
field.offset64);
}
if (TypeHasKey(vtype)) {
code_.SetValue("PARAM_TYPE", "std::vector<" + type + "> *");
@@ -1793,7 +1860,8 @@ class CppGenerator : public BaseGenerator {
if (field.IsScalarOptional())
code_.SetValue("PARAM_TYPE", GenOptionalDecl(type) + " ");
else
code_.SetValue("PARAM_TYPE", GenTypeWire(type, " ", true));
code_.SetValue("PARAM_TYPE",
GenTypeWire(type, " ", true, field.offset64));
}
code_ += "{{PRE}}{{PARAM_TYPE}}{{PARAM_NAME}} = {{PARAM_VALUE}}\\";
}
@@ -1802,11 +1870,11 @@ class CppGenerator : public BaseGenerator {
void GenMember(const FieldDef &field) {
if (!field.deprecated && // Deprecated fields won't be accessible.
field.value.type.base_type != BASE_TYPE_UTYPE &&
(field.value.type.base_type != BASE_TYPE_VECTOR ||
(!IsVector(field.value.type) ||
field.value.type.element != BASE_TYPE_UTYPE)) {
auto type = GenTypeNative(field.value.type, false, field);
auto cpp_type = field.attributes.Lookup("cpp_type");
auto full_type =
const std::string &full_type =
(cpp_type
? (IsVector(field.value.type)
? "std::vector<" +
@@ -1906,7 +1974,7 @@ class CppGenerator : public BaseGenerator {
Name(field) + "(" + native_default->constant + ")";
}
}
} else if (cpp_type && field.value.type.base_type != BASE_TYPE_VECTOR) {
} else if (cpp_type && !IsVector(field.value.type)) {
if (!initializer_list.empty()) { initializer_list += ",\n "; }
initializer_list += Name(field) + "(0)";
}
@@ -1953,9 +2021,10 @@ class CppGenerator : public BaseGenerator {
if (!initializer_list.empty()) { initializer_list += ",\n "; }
const auto cpp_type = field->attributes.Lookup("cpp_type");
const auto cpp_ptr_type = field->attributes.Lookup("cpp_ptr_type");
auto type_name = (cpp_type) ? cpp_type->constant
: GenTypeNative(type, /*invector*/ false,
*field, /*forcopy*/ true);
const std::string &type_name =
(cpp_type) ? cpp_type->constant
: GenTypeNative(type, /*invector*/ false, *field,
/*forcopy*/ true);
const bool is_ptr = !(IsStruct(type) && field->native_inline) ||
(cpp_type && cpp_ptr_type->constant != "naked");
CodeWriter cw;
@@ -1975,10 +2044,10 @@ class CppGenerator : public BaseGenerator {
if (vec_type.base_type == BASE_TYPE_UTYPE) continue;
const auto cpp_type = field->attributes.Lookup("cpp_type");
const auto cpp_ptr_type = field->attributes.Lookup("cpp_ptr_type");
const auto type_name = (cpp_type)
? cpp_type->constant
: GenTypeNative(vec_type, /*invector*/ true,
*field, /*forcopy*/ true);
const std::string &type_name =
(cpp_type) ? cpp_type->constant
: GenTypeNative(vec_type, /*invector*/ true, *field,
/*forcopy*/ true);
const bool is_ptr = IsVectorOfPointers(*field) ||
(cpp_type && cpp_ptr_type->constant != "naked");
CodeWriter cw(" ");
@@ -2050,7 +2119,7 @@ class CppGenerator : public BaseGenerator {
const auto rhs_accessor = "rhs." + accessor;
if (!field.deprecated && // Deprecated fields won't be accessible.
field.value.type.base_type != BASE_TYPE_UTYPE &&
(field.value.type.base_type != BASE_TYPE_VECTOR ||
(!IsVector(field.value.type) ||
field.value.type.element != BASE_TYPE_UTYPE)) {
if (!compare_op.empty()) { compare_op += " &&\n "; }
if (struct_def.fixed || field.native_inline ||
@@ -2150,6 +2219,15 @@ class CppGenerator : public BaseGenerator {
code_ += "";
}
// Adds a typedef to the binary schema type so one could get the bfbs based
// on the type at runtime.
void GenBinarySchemaTypeDef(const StructDef *struct_def) {
if (struct_def && opts_.binary_schema_gen_embed) {
code_ += " typedef " + WrapInNameSpace(*struct_def) +
"BinarySchema BinarySchema;";
}
}
void GenNativeTablePost(const StructDef &struct_def) {
if (opts_.gen_compare) {
const auto native_name = NativeName(Name(struct_def), &struct_def, opts_);
@@ -2173,7 +2251,10 @@ class CppGenerator : public BaseGenerator {
"{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, "
"{{OFFSET}}, {{ALIGN}})\\";
} else {
code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\";
code_.SetValue("OFFSET_SIZE", field.offset64 ? "64" : "");
code_ +=
"{{PRE}}VerifyOffset{{OFFSET_SIZE}}{{REQUIRED}}(verifier, "
"{{OFFSET}})\\";
}
switch (field.value.type.base_type) {
@@ -2195,6 +2276,7 @@ class CppGenerator : public BaseGenerator {
code_ += "{{PRE}}verifier.VerifyString({{NAME}}())\\";
break;
}
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
code_ += "{{PRE}}verifier.VerifyVector({{NAME}}())\\";
@@ -2446,12 +2528,18 @@ class CppGenerator : public BaseGenerator {
if (!field.IsScalarOptional()) {
const bool is_scalar = IsScalar(type.base_type);
std::string accessor;
if (is_scalar)
std::string offset_size = "";
if (is_scalar) {
accessor = "GetField<";
else if (IsStruct(type))
} else if (IsStruct(type)) {
accessor = "GetStruct<";
else
accessor = "GetPointer<";
} else {
if (field.offset64) {
accessor = "GetPointer64<";
} else {
accessor = "GetPointer<";
}
}
auto offset_type = GenTypeGet(type, "", "const ", " *", false);
auto call = accessor + offset_type + ">(" + offset_str;
// Default value as second arg for non-pointer types.
@@ -2611,7 +2699,7 @@ class CppGenerator : public BaseGenerator {
auto offset_str = GenFieldOffsetName(field);
if (is_scalar) {
const auto wire_type = GenTypeWire(type, "", false);
const auto wire_type = GenTypeWire(type, "", false, field.offset64);
code_.SetValue("SET_FN", "SetField<" + wire_type + ">");
code_.SetValue("OFFSET_NAME", offset_str);
code_.SetValue("FIELD_TYPE", GenTypeBasic(type, true));
@@ -2643,7 +2731,11 @@ class CppGenerator : public BaseGenerator {
} else {
auto postptr = " *" + NullableExtension();
auto wire_type = GenTypeGet(type, " ", "", postptr.c_str(), true);
std::string accessor = IsStruct(type) ? "GetStruct<" : "GetPointer<";
const std::string accessor = [&]() {
if (IsStruct(type)) { return "GetStruct<"; }
if (field.offset64) { return "GetPointer64<"; }
return "GetPointer<";
}();
auto underlying = accessor + wire_type + ">(" + offset_str + ")";
code_.SetValue("FIELD_TYPE", wire_type);
code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, underlying));
@@ -2685,6 +2777,8 @@ class CppGenerator : public BaseGenerator {
code_ += " typedef {{NATIVE_NAME}} NativeTableType;";
}
code_ += " typedef {{STRUCT_NAME}}Builder Builder;";
GenBinarySchemaTypeDef(parser_.root_struct_def_);
if (opts_.g_cpp_std >= cpp::CPP_STD_17) { code_ += " struct Traits;"; }
if (opts_.mini_reflect != IDLOptions::kNone) {
code_ +=
@@ -2732,9 +2826,10 @@ class CppGenerator : public BaseGenerator {
if (!nfn.empty()) {
code_.SetValue("CPP_NAME", nfn);
code_ += " const {{CPP_NAME}} *{{FIELD_NAME}}_nested_root() const {";
code_ += " const auto _f = {{FIELD_NAME}}();";
code_ +=
" return "
"::flatbuffers::GetRoot<{{CPP_NAME}}>({{FIELD_NAME}}()->Data());";
" return _f ? ::flatbuffers::GetRoot<{{CPP_NAME}}>(_f->Data())";
code_ += " : nullptr;";
code_ += " }";
}
@@ -2744,9 +2839,9 @@ class CppGenerator : public BaseGenerator {
" const {";
// Both Data() and size() are const-methods, therefore call order
// doesn't matter.
code_ +=
" return flexbuffers::GetRoot({{FIELD_NAME}}()->Data(), "
"{{FIELD_NAME}}()->size());";
code_ += " const auto _f = {{FIELD_NAME}}();";
code_ += " return _f ? flexbuffers::GetRoot(_f->Data(), _f->size())";
code_ += " : flexbuffers::Reference();";
code_ += " }";
}
@@ -2834,10 +2929,13 @@ class CppGenerator : public BaseGenerator {
// Generate code to do force_align for the vector.
if (align > 1) {
const auto vtype = field.value.type.VectorType();
const auto type = IsStruct(vtype) ? WrapInNameSpace(*vtype.struct_def)
: GenTypeWire(vtype, "", false);
return "_fbb.ForceVectorAlignment(" + field_size + ", sizeof(" + type +
"), " + std::to_string(static_cast<long long>(align)) + ");";
const std::string &type =
IsStruct(vtype) ? WrapInNameSpace(*vtype.struct_def)
: GenTypeWire(vtype, "", false, field.offset64);
return std::string("_fbb.ForceVectorAlignment") +
(field.offset64 ? "64" : "") + "(" + field_size + ", sizeof(" +
type + "), " + std::to_string(static_cast<long long>(align)) +
");";
}
return "";
}
@@ -2848,7 +2946,7 @@ class CppGenerator : public BaseGenerator {
// Generate a builder struct:
code_ += "struct {{STRUCT_NAME}}Builder {";
code_ += " typedef {{STRUCT_NAME}} Table;";
code_ += " ::flatbuffers::FlatBufferBuilder &fbb_;";
code_ += " " + GetBuilder() + " &fbb_;";
code_ += " ::flatbuffers::uoffset_t start_;";
bool has_string_or_vector_fields = false;
@@ -2871,12 +2969,14 @@ class CppGenerator : public BaseGenerator {
// fbb_.AddElement<type>(offset, name, default);
// }
code_.SetValue("FIELD_NAME", Name(field));
code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true));
code_.SetValue("FIELD_TYPE",
GenTypeWire(field.value.type, " ", true, field.offset64));
code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset);
code_.SetValue("ADD_NAME", name);
code_.SetValue("ADD_VALUE", value);
if (is_scalar) {
const auto type = GenTypeWire(field.value.type, "", false);
const auto type =
GenTypeWire(field.value.type, "", false, field.offset64);
code_.SetValue("ADD_FN", "AddElement<" + type + ">");
} else if (IsStruct(field.value.type)) {
code_.SetValue("ADD_FN", "AddStruct");
@@ -2895,9 +2995,9 @@ class CppGenerator : public BaseGenerator {
}
// Builder constructor
code_ +=
" explicit {{STRUCT_NAME}}Builder(::flatbuffers::FlatBufferBuilder "
"&_fbb)";
code_ += " explicit {{STRUCT_NAME}}Builder(" + GetBuilder() +
" "
"&_fbb)";
code_ += " : fbb_(_fbb) {";
code_ += " start_ = fbb_.StartTable();";
code_ += " }";
@@ -2924,7 +3024,7 @@ class CppGenerator : public BaseGenerator {
code_ +=
"inline ::flatbuffers::Offset<{{STRUCT_NAME}}> "
"Create{{STRUCT_NAME}}(";
code_ += " ::flatbuffers::FlatBufferBuilder &_fbb\\";
code_ += " " + GetBuilder() + " &_fbb\\";
for (const auto &field : struct_def.fields.vec) {
if (!field->deprecated) { GenParam(*field, false, ",\n "); }
}
@@ -2962,7 +3062,7 @@ class CppGenerator : public BaseGenerator {
code_ +=
"inline ::flatbuffers::Offset<{{STRUCT_NAME}}> "
"Create{{STRUCT_NAME}}Direct(";
code_ += " ::flatbuffers::FlatBufferBuilder &_fbb\\";
code_ += " " + GetBuilder() + " &_fbb\\";
for (const auto &field : struct_def.fields.vec) {
if (!field->deprecated) { GenParam(*field, true, ",\n "); }
}
@@ -2971,54 +3071,85 @@ class CppGenerator : public BaseGenerator {
struct_def.defined_namespace->GetFullyQualifiedName("Create");
code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name));
code_ += ") {";
for (const auto &field : struct_def.fields.vec) {
if (!field->deprecated) {
code_.SetValue("FIELD_NAME", Name(*field));
if (IsString(field->value.type)) {
if (!field->shared) {
code_.SetValue("CREATE_STRING", "CreateString");
} else {
code_.SetValue("CREATE_STRING", "CreateSharedString");
}
code_ +=
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
"_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : 0;";
} else if (IsVector(field->value.type)) {
const std::string force_align_code =
GenVectorForceAlign(*field, Name(*field) + "->size()");
if (!force_align_code.empty()) {
code_ += " if ({{FIELD_NAME}}) { " + force_align_code + " }";
}
code_ += " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\";
const auto vtype = field->value.type.VectorType();
const auto has_key = TypeHasKey(vtype);
if (IsStruct(vtype)) {
const auto type = WrapInNameSpace(*vtype.struct_def);
code_ += (has_key ? "_fbb.CreateVectorOfSortedStructs<"
: "_fbb.CreateVectorOfStructs<") +
type + ">\\";
} else if (has_key) {
const auto type = WrapInNameSpace(*vtype.struct_def);
code_ += "_fbb.CreateVectorOfSortedTables<" + type + ">\\";
} else {
const auto type =
GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
code_ += "_fbb.CreateVector<" + type + ">\\";
}
code_ +=
has_key ? "({{FIELD_NAME}}) : 0;" : "(*{{FIELD_NAME}}) : 0;";
// Offset64 bit fields need to be added to the buffer first, so here we
// loop over the fields in order of their offset size, followed by their
// definition order. Otherwise the emitted code might add a Offset
// followed by an Offset64 which would trigger an assertion.
// TODO(derekbailey): maybe optimize for the case where there is no
// 64offsets in the whole schema?
ForAllFieldsOrderedByOffset(struct_def, [&](const FieldDef *field) {
if (field->deprecated) { return; }
code_.SetValue("FIELD_NAME", Name(*field));
if (IsString(field->value.type)) {
if (!field->shared) {
code_.SetValue(
"CREATE_STRING",
"CreateString" + std::string(field->offset64
? "<::flatbuffers::Offset64>"
: ""));
} else {
code_.SetValue("CREATE_STRING", "CreateSharedString");
}
code_ +=
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
"_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : 0;";
} else if (IsVector(field->value.type)) {
const std::string force_align_code =
GenVectorForceAlign(*field, Name(*field) + "->size()");
if (!force_align_code.empty()) {
code_ += " if ({{FIELD_NAME}}) { " + force_align_code + " }";
}
code_ += " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\";
const auto vtype = field->value.type.VectorType();
const auto has_key = TypeHasKey(vtype);
if (IsStruct(vtype)) {
const std::string type = WrapInNameSpace(*vtype.struct_def);
if (has_key) {
code_ += "_fbb.CreateVectorOfSortedStructs<" + type + ">\\";
} else {
// If the field uses 64-bit addressing, create a 64-bit vector.
if (field->value.type.base_type == BASE_TYPE_VECTOR64) {
code_ += "_fbb.CreateVectorOfStructs64\\";
} else {
code_ += "_fbb.CreateVectorOfStructs\\";
if (field->offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code_ += "64<::flatbuffers::Vector>\\";
} else {
code_ += "<" + type + ">\\";
}
}
}
} else if (has_key) {
const auto type = WrapInNameSpace(*vtype.struct_def);
code_ += "_fbb.CreateVectorOfSortedTables<" + type + ">\\";
} else {
const auto type = GenTypeWire(
vtype, "", VectorElementUserFacing(vtype), field->offset64);
if (field->value.type.base_type == BASE_TYPE_VECTOR64) {
code_ += "_fbb.CreateVector64\\";
} else {
// If the field uses 64-bit addressing, create a 64-bit vector.
code_.SetValue("64OFFSET", field->offset64 ? "64" : "");
code_.SetValue("TYPE",
field->offset64 ? "::flatbuffers::Vector" : type);
code_ += "_fbb.CreateVector{{64OFFSET}}<{{TYPE}}>\\";
}
}
code_ += has_key ? "({{FIELD_NAME}}) : 0;" : "(*{{FIELD_NAME}}) : 0;";
}
}
});
code_ += " return {{CREATE_NAME}}{{STRUCT_NAME}}(";
code_ += " _fbb\\";
for (const auto &field : struct_def.fields.vec) {
if (!field->deprecated) {
code_.SetValue("FIELD_NAME", Name(*field));
code_ += ",\n {{FIELD_NAME}}\\";
if (IsString(field->value.type) || IsVector(field->value.type)) {
code_ += "__\\";
}
if (field->deprecated) { continue; }
code_.SetValue("FIELD_NAME", Name(*field));
code_ += ",\n {{FIELD_NAME}}\\";
if (IsString(field->value.type) || IsVector(field->value.type)) {
code_ += "__\\";
}
}
code_ += ");";
@@ -3089,6 +3220,7 @@ class CppGenerator : public BaseGenerator {
const FieldDef *union_field) {
std::string code;
switch (field.value.type.base_type) {
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
auto name = Name(field);
if (field.value.type.element == BASE_TYPE_UTYPE) {
@@ -3125,8 +3257,11 @@ class CppGenerator : public BaseGenerator {
? ".type"
: (field.value.type.element == BASE_TYPE_UNION ? ".value"
: "");
code += "for (::flatbuffers::uoffset_t _i = 0;";
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
code += "for (::flatbuffers::uoffset64_t _i = 0;";
} else {
code += "for (::flatbuffers::uoffset_t _i = 0;";
}
code += " _i < _e->size(); _i++) { ";
auto cpp_type = field.attributes.Lookup("cpp_type");
if (cpp_type) {
@@ -3239,8 +3374,7 @@ class CppGenerator : public BaseGenerator {
} else {
value += Name(field);
}
if (field.value.type.base_type != BASE_TYPE_VECTOR &&
field.attributes.Lookup("cpp_type")) {
if (!IsVector(field.value.type) && field.attributes.Lookup("cpp_type")) {
auto type = GenTypeBasic(field.value.type, false);
value =
"_rehasher ? "
@@ -3256,7 +3390,10 @@ class CppGenerator : public BaseGenerator {
// _fbb.CreateSharedString(_o->field)
case BASE_TYPE_STRING: {
if (!field.shared) {
code += "_fbb.CreateString(";
code +=
"_fbb.CreateString" +
std::string(field.offset64 ? "<::flatbuffers::Offset64>" : "") +
"(";
} else {
code += "_fbb.CreateSharedString(";
}
@@ -3283,6 +3420,7 @@ class CppGenerator : public BaseGenerator {
// _fbb.CreateVector<Offset<T>>(_o->field.size() [&](size_t i) {
// return CreateT(_fbb, _o->Get(i), rehasher);
// });
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
auto vector_type = field.value.type.VectorType();
switch (vector_type.base_type) {
@@ -3321,7 +3459,16 @@ class CppGenerator : public BaseGenerator {
}
code += ")";
} else {
code += "_fbb.CreateVectorOfStructs";
// If the field uses 64-bit addressing, create a 64-bit vector.
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
code += "_fbb.CreateVectorOfStructs64";
} else {
code += "_fbb.CreateVectorOfStructs";
if (field.offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code += "64<::flatbuffers::Vector>";
}
}
code += "(" + value + ")";
}
} else {
@@ -3356,11 +3503,14 @@ class CppGenerator : public BaseGenerator {
}
case BASE_TYPE_UTYPE: {
value = StripUnionType(value);
auto type = opts_.scoped_enums ? Name(*field.value.type.enum_def)
: "uint8_t";
auto underlying_type = GenTypeBasic(vector_type, false);
const std::string &type = opts_.scoped_enums
? Name(*field.value.type.enum_def)
: underlying_type;
auto enum_value = "__va->_" + value + "[i].type";
if (!opts_.scoped_enums)
enum_value = "static_cast<uint8_t>(" + enum_value + ")";
enum_value =
"static_cast<" + underlying_type + ">(" + enum_value + ")";
code += "_fbb.CreateVector<" + type + ">(" + value +
".size(), [](size_t i, _VectorArgs *__va) { return " +
@@ -3386,7 +3536,17 @@ class CppGenerator : public BaseGenerator {
code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0";
code += "; }, &_va )";
} else {
code += "_fbb.CreateVector(" + value + ")";
// If the field uses 64-bit addressing, create a 64-bit vector.
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
code += "_fbb.CreateVector64(" + value + ")";
} else {
code += "_fbb.CreateVector";
if (field.offset64) {
// This is normal 32-bit vector, with 64-bit addressing.
code += "64<::flatbuffers::Vector>";
}
code += "(" + value + ")";
}
}
break;
}
@@ -3423,7 +3583,7 @@ class CppGenerator : public BaseGenerator {
}
} else {
// _o->field ? CreateT(_fbb, _o->field.get(), _rehasher);
const auto type = field.value.type.struct_def->name;
const std::string &type = field.value.type.struct_def->name;
code += value + " ? Create" + type;
code += "(_fbb, " + value;
if (!field.native_inline) code += GenPtrGet(field);
@@ -3513,7 +3673,9 @@ class CppGenerator : public BaseGenerator {
code_ +=
" struct _VectorArgs "
"{ ::flatbuffers::FlatBufferBuilder *__fbb; "
"{ " +
GetBuilder() +
" *__fbb; "
"const " +
NativeName(Name(struct_def), &struct_def, opts_) +
"* __o; "
@@ -3809,7 +3971,7 @@ class CppGenerator : public BaseGenerator {
const auto field_type = GenTypeGet(type, " ", is_array ? "" : "const ",
is_array ? "" : " &", true);
auto member = Name(*field) + "_";
auto value =
const std::string &value =
is_scalar ? "::flatbuffers::EndianScalar(" + member + ")" : member;
code_.SetValue("FIELD_NAME", Name(*field));
@@ -3913,12 +4075,12 @@ class CppGenerator : public BaseGenerator {
} // namespace cpp
bool GenerateCPP(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateCPP(const Parser &parser, const std::string &path,
const std::string &file_name) {
cpp::IDLOptionsCpp opts(parser.opts);
// The '--cpp_std' argument could be extended (like ASAN):
// Example: "flatc --cpp_std c++17:option1:option2".
auto cpp_std = !opts.cpp_std.empty() ? opts.cpp_std : "C++11";
std::string cpp_std = !opts.cpp_std.empty() ? opts.cpp_std : "C++11";
std::transform(cpp_std.begin(), cpp_std.end(), cpp_std.begin(), CharToUpper);
if (cpp_std == "C++0X") {
opts.g_cpp_std = cpp::CPP_STD_X0;
@@ -3952,8 +4114,8 @@ bool GenerateCPP(const Parser &parser, const std::string &path,
return generator.generate();
}
std::string CPPMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
static std::string CPPMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
const auto filebase = StripPath(StripExtension(file_name));
cpp::CppGenerator geneartor(parser, path, file_name, parser.opts);
const auto included_files = parser.GetIncludedFilesRecursive(file_name);
@@ -3977,9 +4139,8 @@ class CppCodeGenerator : public CodeGenerator {
// Generate code from the provided `buffer` of given `length`. The buffer is a
// serialized reflection.fbs.
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+73 -54
View File
@@ -625,7 +625,8 @@ class CSharpGenerator : public BaseGenerator {
}
// Get the value of a table verification function start
void GetStartOfTableVerifier(const StructDef &struct_def, std::string *code_ptr) {
void GetStartOfTableVerifier(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "\n";
code += "static public class " + struct_def.name + "Verify\n";
@@ -645,17 +646,18 @@ class CSharpGenerator : public BaseGenerator {
}
std::string GetNestedFlatBufferName(const FieldDef &field) {
std::string name;
std::string name;
if (field.nested_flatbuffer) {
name = NamespacedName(*field.nested_flatbuffer);
} else {
name = "";
}
return name ;
return name;
}
// Generate the code to call the appropriate Verify function(s) for a field.
void GenVerifyCall(CodeWriter &code_, const FieldDef &field, const char *prefix) {
void GenVerifyCall(CodeWriter &code_, const FieldDef &field,
const char *prefix) {
code_.SetValue("PRE", prefix);
code_.SetValue("NAME", ConvertCase(field.name, Case::kUpperCamel));
code_.SetValue("REQUIRED", field.IsRequired() ? "Required" : "");
@@ -663,14 +665,16 @@ class CSharpGenerator : public BaseGenerator {
code_.SetValue("TYPE", GenTypeGet(field.value.type));
code_.SetValue("INLINESIZE", NumToString(InlineSize(field.value.type)));
code_.SetValue("OFFSET", NumToString(field.value.offset));
if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) {
code_.SetValue("ALIGN", NumToString(InlineAlignment(field.value.type)));
code_ +=
"{{PRE}} && verifier.VerifyField(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{INLINESIZE}} /*{{TYPE}}*/, {{ALIGN}}, {{REQUIRED_FLAG}})";
"{{PRE}} && verifier.VerifyField(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{INLINESIZE}} /*{{TYPE}}*/, {{ALIGN}}, "
"{{REQUIRED_FLAG}})";
} else {
// TODO - probably code below should go to this 'else' - code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\";
// TODO - probably code below should go to this 'else' - code_ +=
// "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\";
}
switch (field.value.type.base_type) {
@@ -679,37 +683,47 @@ class CSharpGenerator : public BaseGenerator {
code_.SetValue("ENUM_NAME1", field.value.type.enum_def->name);
code_.SetValue("ENUM_NAME", union_name);
code_.SetValue("SUFFIX", UnionTypeFieldSuffix());
// Caution: This construction assumes, that UNION type id element has been created just before union data and
// its offset precedes union. Such assumption is common in flatbuffer implementation
code_.SetValue("TYPE_ID_OFFSET", NumToString(field.value.offset - sizeof(voffset_t)));
code_ += "{{PRE}} && verifier.VerifyUnion(tablePos, {{TYPE_ID_OFFSET}}, "
"{{OFFSET}} /*{{NAME}}*/, {{ENUM_NAME}}Verify.Verify, {{REQUIRED_FLAG}})";
// Caution: This construction assumes, that UNION type id element has
// been created just before union data and its offset precedes union.
// Such assumption is common in flatbuffer implementation
code_.SetValue("TYPE_ID_OFFSET",
NumToString(field.value.offset - sizeof(voffset_t)));
code_ +=
"{{PRE}} && verifier.VerifyUnion(tablePos, "
"{{TYPE_ID_OFFSET}}, "
"{{OFFSET}} /*{{NAME}}*/, {{ENUM_NAME}}Verify.Verify, "
"{{REQUIRED_FLAG}})";
break;
}
case BASE_TYPE_STRUCT: {
if (!field.value.type.struct_def->fixed) {
code_ += "{{PRE}} && verifier.VerifyTable(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{TYPE}}Verify.Verify, {{REQUIRED_FLAG}})";
code_ +=
"{{PRE}} && verifier.VerifyTable(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{TYPE}}Verify.Verify, "
"{{REQUIRED_FLAG}})";
}
break;
}
case BASE_TYPE_STRING: {
code_ += "{{PRE}} && verifier.VerifyString(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{REQUIRED_FLAG}})";
code_ +=
"{{PRE}} && verifier.VerifyString(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{REQUIRED_FLAG}})";
break;
}
case BASE_TYPE_VECTOR: {
switch (field.value.type.element) {
case BASE_TYPE_STRING: {
code_ += "{{PRE}} && verifier.VerifyVectorOfStrings(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{REQUIRED_FLAG}})";
code_ +=
"{{PRE}} && verifier.VerifyVectorOfStrings(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{REQUIRED_FLAG}})";
break;
}
case BASE_TYPE_STRUCT: {
if (!field.value.type.struct_def->fixed) {
code_ += "{{PRE}} && verifier.VerifyVectorOfTables(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{TYPE}}Verify.Verify, {{REQUIRED_FLAG}})";
code_ +=
"{{PRE}} && verifier.VerifyVectorOfTables(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{TYPE}}Verify.Verify, "
"{{REQUIRED_FLAG}})";
} else {
code_.SetValue(
"VECTOR_ELEM_INLINESIZE",
@@ -733,16 +747,22 @@ class CSharpGenerator : public BaseGenerator {
if (!nfn.empty()) {
code_.SetValue("CPP_NAME", nfn);
// FIXME: file_identifier.
code_ += "{{PRE}} && verifier.VerifyNestedBuffer(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{CPP_NAME}}Verify.Verify, {{REQUIRED_FLAG}})";
} else if (field.flexbuffer) {
code_ += "{{PRE}} && verifier.VerifyNestedBuffer(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, null, {{REQUIRED_FLAG}})";
} else {
code_.SetValue("VECTOR_ELEM_INLINESIZE", NumToString(InlineSize(field.value.type.VectorType())));
code_ +=
"{{PRE}} && verifier.VerifyVectorOfData(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{VECTOR_ELEM_INLINESIZE}} /*{{TYPE}}*/, {{REQUIRED_FLAG}})";
"{{PRE}} && verifier.VerifyNestedBuffer(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{CPP_NAME}}Verify.Verify, "
"{{REQUIRED_FLAG}})";
} else if (field.flexbuffer) {
code_ +=
"{{PRE}} && verifier.VerifyNestedBuffer(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, null, {{REQUIRED_FLAG}})";
} else {
code_.SetValue(
"VECTOR_ELEM_INLINESIZE",
NumToString(InlineSize(field.value.type.VectorType())));
code_ +=
"{{PRE}} && verifier.VerifyVectorOfData(tablePos, "
"{{OFFSET}} /*{{NAME}}*/, {{VECTOR_ELEM_INLINESIZE}} "
"/*{{TYPE}}*/, {{REQUIRED_FLAG}})";
}
break;
}
@@ -758,7 +778,7 @@ class CSharpGenerator : public BaseGenerator {
// Generate table constructors, conditioned on its members' types.
void GenTableVerifier(const StructDef &struct_def, std::string *code_ptr) {
CodeWriter code_;
GetStartOfTableVerifier(struct_def, code_ptr);
// Generate struct fields accessors
@@ -771,7 +791,7 @@ class CSharpGenerator : public BaseGenerator {
}
*code_ptr += code_.ToString();
GetEndOfTableVerifier(code_ptr);
}
@@ -787,7 +807,7 @@ class CSharpGenerator : public BaseGenerator {
// verification - instead structure size is verified using VerifyField
} else {
// Create table verification function
GenTableVerifier(struct_def, code_ptr);
GenTableVerifier(struct_def, code_ptr);
}
}
@@ -826,7 +846,7 @@ class CSharpGenerator : public BaseGenerator {
// Force compile time error if not using the same version runtime.
code += " public static void ValidateVersion() {";
code += " FlatBufferConstants.";
code += "FLATBUFFERS_23_3_3(); ";
code += "FLATBUFFERS_23_5_26(); ";
code += "}\n";
// Generate a special accessor for the table that when used as the root
@@ -1602,8 +1622,7 @@ class CSharpGenerator : public BaseGenerator {
if (union_type.enum_def) {
const auto &enum_def = *union_type.enum_def;
auto ret =
"\n\nstatic public class " + enum_def.name + "Verify\n";
auto ret = "\n\nstatic public class " + enum_def.name + "Verify\n";
ret += "{\n";
ret +=
" static public bool Verify(Google.FlatBuffers.Verifier verifier, "
@@ -1615,25 +1634,26 @@ class CSharpGenerator : public BaseGenerator {
ret += " switch((" + enum_def.name + ")typeId)\n";
ret += " {\n";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
++it) {
const auto &ev = **it;
if (ev.IsZero()) { continue; }
ret += " case " + Name(enum_def) + "." + Name(ev) + ":\n";
if (IsString(ev.union_type)) {
ret +=
" result = verifier.VerifyUnionString(tablePos);\n";
ret += " result = verifier.VerifyUnionString(tablePos);\n";
ret += " break;";
} else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
if (! ev.union_type.struct_def->fixed) {
if (!ev.union_type.struct_def->fixed) {
auto type = GenTypeGet(ev.union_type);
ret += " result = " + type + "Verify.Verify(verifier, tablePos);\n";
ret += " result = " + type +
"Verify.Verify(verifier, tablePos);\n";
} else {
ret += " result = verifier.VerifyUnionData(tablePos, " +
NumToString(InlineSize(ev.union_type)) + ", " +
NumToString(InlineAlignment(ev.union_type)) +
");\n";;
NumToString(InlineSize(ev.union_type)) + ", " +
NumToString(InlineAlignment(ev.union_type)) + ");\n";
;
}
ret += " break;";
} else {
@@ -1676,7 +1696,7 @@ class CSharpGenerator : public BaseGenerator {
// Type
code += " public " + enum_def.name + " Type { get; set; }\n";
// Value
code += " public object " + class_member + " { get; set; }\n";
code += " public object " + class_member + " { get; set; }\n";
code += "\n";
// Constructor
code += " public " + union_name + "() {\n";
@@ -1736,7 +1756,7 @@ class CSharpGenerator : public BaseGenerator {
code += "}\n\n";
code += GenUnionVerify(enum_def.underlying_type);
// JsonConverter
if (opts.cs_gen_json_serializer) {
if (enum_def.attributes.Lookup("private")) {
@@ -1773,7 +1793,7 @@ class CSharpGenerator : public BaseGenerator {
" _o, "
"Newtonsoft.Json.JsonSerializer serializer) {\n";
code += " if (_o == null) return;\n";
code += " serializer.Serialize(writer, _o." + class_member + ");\n";
code += " serializer.Serialize(writer, _o." + class_member + ");\n";
code += " }\n";
code +=
" public override object ReadJson(Newtonsoft.Json.JsonReader "
@@ -2498,8 +2518,8 @@ class CSharpGenerator : public BaseGenerator {
};
} // namespace csharp
bool GenerateCSharp(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateCSharp(const Parser &parser, const std::string &path,
const std::string &file_name) {
csharp::CSharpGenerator generator(parser, path, file_name);
return generator.generate();
}
@@ -2514,16 +2534,15 @@ class CSharpCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
Status GenerateMakeRule(const Parser &parser, const std::string &path,
const std::string &filename,
std::string &output) override {
output = CSharpMakeRule(parser, path, filename);
output = JavaCSharpMakeRule(false, parser, path, filename);
return Status::OK;
}
+9 -12
View File
@@ -90,8 +90,8 @@ class DartGenerator : public BaseGenerator {
template<typename T>
void import_generator(const std::vector<T *> &definitions,
const std::string &included,
std::set<std::string> &imports) {
const std::string &included,
std::set<std::string> &imports) {
for (const auto &item : definitions) {
if (item->file == included) {
std::string component = namer_.Namespace(*item->defined_namespace);
@@ -760,9 +760,7 @@ class DartGenerator : public BaseGenerator {
std::string getDefaultValue(const Value &value) const {
if (!value.constant.empty() && value.constant != "0") {
if (IsBool(value.type.base_type)) {
return "true";
}
if (IsBool(value.type.base_type)) { return "true"; }
if (IsScalar(value.type.base_type)) {
if (StringIsFlatbufferNan(value.constant)) {
return "double.nan";
@@ -1124,14 +1122,14 @@ class DartGenerator : public BaseGenerator {
};
} // namespace dart
bool GenerateDart(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateDart(const Parser &parser, const std::string &path,
const std::string &file_name) {
dart::DartGenerator generator(parser, path, file_name);
return generator.generate();
}
std::string DartMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
static std::string DartMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
auto filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
dart::DartGenerator generator(parser, path, file_name);
@@ -1154,9 +1152,8 @@ class DartCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+55 -30
View File
@@ -28,6 +28,7 @@
#include "flatbuffers/util.h"
namespace flatbuffers {
namespace {
static std::string GenType(const Type &type, bool underlying = false) {
switch (type.base_type) {
@@ -129,34 +130,43 @@ static bool HasGapInProtoId(const std::vector<FieldDef *> &fields) {
}
static bool ProtobufIdSanityCheck(const StructDef &struct_def,
IDLOptions::ProtoIdGapAction gap_action) {
IDLOptions::ProtoIdGapAction gap_action,
bool no_log = false) {
const auto &fields = struct_def.fields.vec;
if (HasNonPositiveFieldId(fields)) {
// TODO: Use LogCompilerWarn
fprintf(stderr, "Field id in struct %s has a non positive number value\n",
struct_def.name.c_str());
if (!no_log) {
fprintf(stderr, "Field id in struct %s has a non positive number value\n",
struct_def.name.c_str());
}
return false;
}
if (HasTwiceUsedId(fields)) {
// TODO: Use LogCompilerWarn
fprintf(stderr, "Fields in struct %s have used an id twice\n",
struct_def.name.c_str());
if (!no_log) {
fprintf(stderr, "Fields in struct %s have used an id twice\n",
struct_def.name.c_str());
}
return false;
}
if (HasFieldIdFromReservedIds(fields, struct_def.reserved_ids)) {
// TODO: Use LogCompilerWarn
fprintf(stderr, "Fields in struct %s use id from reserved ids\n",
struct_def.name.c_str());
if (!no_log) {
fprintf(stderr, "Fields in struct %s use id from reserved ids\n",
struct_def.name.c_str());
}
return false;
}
if (gap_action != IDLOptions::ProtoIdGapAction::NO_OP) {
if (HasGapInProtoId(fields)) {
// TODO: Use LogCompilerWarn
fprintf(stderr, "Fields in struct %s have gap between ids\n",
struct_def.name.c_str());
if (!no_log) {
fprintf(stderr, "Fields in struct %s have gap between ids\n",
struct_def.name.c_str());
}
if (gap_action == IDLOptions::ProtoIdGapAction::ERROR) { return false; }
}
}
@@ -174,7 +184,8 @@ struct ProtobufToFbsIdMap {
};
static ProtobufToFbsIdMap MapProtoIdsToFieldsId(
const StructDef &struct_def, IDLOptions::ProtoIdGapAction gap_action) {
const StructDef &struct_def, IDLOptions::ProtoIdGapAction gap_action,
bool no_log) {
const auto &fields = struct_def.fields.vec;
if (!HasFieldWithId(fields)) {
@@ -183,7 +194,7 @@ static ProtobufToFbsIdMap MapProtoIdsToFieldsId(
return result;
}
if (!ProtobufIdSanityCheck(struct_def, gap_action)) { return {}; }
if (!ProtobufIdSanityCheck(struct_def, gap_action, no_log)) { return {}; }
static constexpr int UNION_ID = -1;
using ProtoIdFieldNamePair = std::pair<int, std::string>;
@@ -203,8 +214,10 @@ static ProtobufToFbsIdMap MapProtoIdsToFieldsId(
}
} else {
// TODO: Use LogCompilerWarn
fprintf(stderr, "Fields id in struct %s is missing\n",
struct_def.name.c_str());
if (!no_log) {
fprintf(stderr, "Fields id in struct %s is missing\n",
struct_def.name.c_str());
}
return {};
}
}
@@ -240,7 +253,9 @@ static void GenNameSpace(const Namespace &name_space, std::string *_schema,
}
// Generate a flatbuffer schema from the Parser's internal representation.
std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
static std::string GenerateFBS(const Parser &parser,
const std::string &file_name,
bool no_log = false) {
// Proto namespaces may clash with table names, escape the ones that were
// generated from a table:
for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end();
@@ -315,8 +330,8 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
++it) {
StructDef &struct_def = **it;
const auto proto_fbs_ids =
MapProtoIdsToFieldsId(struct_def, parser.opts.proto_id_gap_action);
const auto proto_fbs_ids = MapProtoIdsToFieldsId(
struct_def, parser.opts.proto_id_gap_action, no_log);
if (!proto_fbs_ids.successful) { return {}; }
if (parser.opts.include_dependence_headers && struct_def.generated) {
@@ -361,32 +376,39 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
return schema;
}
bool GenerateFBS(const Parser &parser, const std::string &path,
const std::string &file_name) {
const std::string fbs = GenerateFBS(parser, file_name);
static bool GenerateFBS(const Parser &parser, const std::string &path,
const std::string &file_name, bool no_log = false) {
const std::string fbs = GenerateFBS(parser, file_name, no_log);
if (fbs.empty()) { return false; }
// TODO: Use LogCompilerWarn
fprintf(stderr,
"When you use --proto, that you should check for conformity "
"yourself, using the existing --conform");
if (!no_log) {
fprintf(stderr,
"When you use --proto, that you should check for conformity "
"yourself, using the existing --conform");
}
return SaveFile((path + file_name + ".fbs").c_str(), fbs, false);
}
namespace {
class FBSCodeGenerator : public CodeGenerator {
public:
explicit FBSCodeGenerator(const bool no_log) : no_log_(no_log) {}
Status GenerateCode(const Parser &parser, const std::string &path,
const std::string &filename) override {
if (!GenerateFBS(parser, path, filename)) { return Status::ERROR; }
if (!GenerateFBS(parser, path, filename, no_log_)) { return Status::ERROR; }
return Status::OK;
}
Status GenerateCodeString(const Parser &parser, const std::string &filename,
std::string &output) override {
output = GenerateFBS(parser, filename, no_log_);
return Status::OK;
}
// Generate code from the provided `buffer` of given `length`. The buffer is a
// serialized reflection.fbs.
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
@@ -424,12 +446,15 @@ class FBSCodeGenerator : public CodeGenerator {
IDLOptions::Language Language() const override { return IDLOptions::kProto; }
std::string LanguageName() const override { return "proto"; }
protected:
const bool no_log_;
};
} // namespace
std::unique_ptr<CodeGenerator> NewFBSCodeGenerator() {
return std::unique_ptr<FBSCodeGenerator>(new FBSCodeGenerator());
std::unique_ptr<CodeGenerator> NewFBSCodeGenerator(const bool no_log) {
return std::unique_ptr<FBSCodeGenerator>(new FBSCodeGenerator(no_log));
}
} // namespace flatbuffers
+1 -1
View File
@@ -21,7 +21,7 @@
namespace flatbuffers {
std::unique_ptr<CodeGenerator> NewFBSCodeGenerator();
std::unique_ptr<CodeGenerator> NewFBSCodeGenerator(bool no_log = false);
} // namespace flatbuffers
+4 -5
View File
@@ -1606,8 +1606,8 @@ class GoGenerator : public BaseGenerator {
};
} // namespace go
bool GenerateGo(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateGo(const Parser &parser, const std::string &path,
const std::string &file_name) {
go::GoGenerator generator(parser, path, file_name, parser.opts.go_namespace);
return generator.generate();
}
@@ -1622,9 +1622,8 @@ class GoCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+25 -32
View File
@@ -69,9 +69,10 @@ static std::set<std::string> JavaKeywords() {
};
}
static const TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
"POSITIVE_INFINITY",
"NEGATIVE_INFINITY");
static const TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.",
"NaN",
"POSITIVE_INFINITY",
"NEGATIVE_INFINITY");
static const CommentConfig comment_config = {
"/**",
@@ -79,7 +80,7 @@ static const CommentConfig comment_config = {
" */",
};
} // namespace
} // namespace
class JavaGenerator : public BaseGenerator {
struct FieldArrayLength {
@@ -89,16 +90,15 @@ class JavaGenerator : public BaseGenerator {
public:
JavaGenerator(const Parser &parser, const std::string &path,
const std::string &file_name,
const std::string &package_prefix)
const std::string &file_name, const std::string &package_prefix)
: BaseGenerator(parser, path, file_name, "", ".", "java"),
cur_name_space_(nullptr),
cur_name_space_(nullptr),
namer_(WithFlagOptions(JavaDefaultConfig(), parser.opts, path),
JavaKeywords()) {
if (!package_prefix.empty()) {
std::istringstream iss(package_prefix);
std::string component;
while(std::getline(iss, component, '.')) {
while (std::getline(iss, component, '.')) {
package_prefix_ns_.components.push_back(component);
}
package_prefix_ = package_prefix_ns_.GetFullyQualifiedName("") + ".";
@@ -184,10 +184,8 @@ class JavaGenerator : public BaseGenerator {
code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
Namespace combined_ns = package_prefix_ns_;
std::copy(
ns.components.begin(),
ns.components.end(),
std::back_inserter(combined_ns.components));
std::copy(ns.components.begin(), ns.components.end(),
std::back_inserter(combined_ns.components));
const std::string namespace_name = FullNamespace(".", combined_ns);
if (!namespace_name.empty()) {
@@ -368,9 +366,9 @@ class JavaGenerator : public BaseGenerator {
FLATBUFFERS_ASSERT(value.type.enum_def);
auto &enum_def = *value.type.enum_def;
auto enum_val = enum_def.FindByValue(value.constant);
return
enum_val ? Prefixed(namer_.NamespacedEnumVariant(enum_def, *enum_val))
: value.constant;
return enum_val
? Prefixed(namer_.NamespacedEnumVariant(enum_def, *enum_val))
: value.constant;
}
std::string GenDefaultValue(const FieldDef &field) const {
@@ -703,7 +701,7 @@ class JavaGenerator : public BaseGenerator {
// Force compile time error if not using the same version runtime.
code += " public static void ValidateVersion() {";
code += " Constants.";
code += "FLATBUFFERS_23_3_3(); ";
code += "FLATBUFFERS_23_5_26(); ";
code += "}\n";
// Generate a special accessor for the table that when used as the root
@@ -1653,9 +1651,9 @@ class JavaGenerator : public BaseGenerator {
break;
case BASE_TYPE_UNION:
array_type = "int";
element_type =
Prefixed(namer_.NamespacedType(*field.value.type.enum_def))
+ "Union";
element_type = Prefixed(namer_.NamespacedType(
*field.value.type.enum_def)) +
"Union";
to_array = element_type + ".pack(builder, _o." +
namer_.Method("get", property_name) + "()[_j])";
break;
@@ -2007,8 +2005,7 @@ class JavaGenerator : public BaseGenerator {
case BASE_TYPE_UNION: {
if (wrap_in_namespace) {
type_name =
Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
type_name = Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
} else {
type_name = namer_.Type(*type.enum_def) + "Union";
}
@@ -2042,15 +2039,13 @@ class JavaGenerator : public BaseGenerator {
type_name.replace(type_name.length() - type_name_length,
type_name_length, new_type_name);
} else if (type.element == BASE_TYPE_UNION) {
type_name =
Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
type_name = Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
}
break;
}
case BASE_TYPE_UNION: {
type_name =
Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
type_name = Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
break;
}
default: break;
@@ -2192,12 +2187,11 @@ class JavaGenerator : public BaseGenerator {
std::string package_prefix_;
Namespace package_prefix_ns_;
};
} // namespace java
bool GenerateJava(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateJava(const Parser &parser, const std::string &path,
const std::string &file_name) {
java::JavaGenerator generator(parser, path, file_name,
parser.opts.java_package_prefix);
return generator.generate();
@@ -2213,16 +2207,15 @@ class JavaCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
Status GenerateMakeRule(const Parser &parser, const std::string &path,
const std::string &filename,
std::string &output) override {
output = JavaMakeRule(parser, path, filename);
output = JavaCSharpMakeRule(true, parser, path, filename);
return Status::OK;
}
+7 -17
View File
@@ -30,8 +30,7 @@ namespace jsons {
namespace {
template<class T>
static std::string GenFullName(const T *enum_def) {
template<class T> static std::string GenFullName(const T *enum_def) {
std::string full_name;
const auto &name_spaces = enum_def->defined_namespace->components;
for (auto ns = name_spaces.cbegin(); ns != name_spaces.cend(); ++ns) {
@@ -41,8 +40,7 @@ static std::string GenFullName(const T *enum_def) {
return full_name;
}
template<class T>
static std::string GenTypeRef(const T *enum_def) {
template<class T> static std::string GenTypeRef(const T *enum_def) {
return "\"$ref\" : \"#/definitions/" + GenFullName(enum_def) + "\"";
}
@@ -144,7 +142,7 @@ static std::string GenType(const Type &type) {
}
}
} // namespace
} // namespace
class JsonSchemaGenerator : public BaseGenerator {
private:
@@ -319,20 +317,13 @@ class JsonSchemaGenerator : public BaseGenerator {
};
} // namespace jsons
bool GenerateJsonSchema(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateJsonSchema(const Parser &parser, const std::string &path,
const std::string &file_name) {
jsons::JsonSchemaGenerator generator(parser, path, file_name);
if (!generator.generate()) { return false; }
return generator.save();
}
bool GenerateJsonSchema(const Parser &parser, std::string *json) {
jsons::JsonSchemaGenerator generator(parser, "", "");
if (!generator.generate()) { return false; }
*json = generator.getJson();
return true;
}
namespace {
class JsonSchemaCodeGenerator : public CodeGenerator {
@@ -343,9 +334,8 @@ class JsonSchemaCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+6 -7
View File
@@ -70,7 +70,7 @@ static Namer::Config KotlinDefaultConfig() {
/*filename_suffix=*/"",
/*filename_extension=*/".kt" };
}
} // namespace
} // namespace
class KotlinGenerator : public BaseGenerator {
public:
@@ -524,7 +524,7 @@ class KotlinGenerator : public BaseGenerator {
// runtime.
GenerateFunOneLine(
writer, "validateVersion", "", "",
[&]() { writer += "Constants.FLATBUFFERS_23_3_3()"; },
[&]() { writer += "Constants.FLATBUFFERS_23_5_26()"; },
options.gen_jvmstatic);
GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options);
@@ -1593,8 +1593,8 @@ class KotlinGenerator : public BaseGenerator {
};
} // namespace kotlin
bool GenerateKotlin(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateKotlin(const Parser &parser, const std::string &path,
const std::string &file_name) {
kotlin::KotlinGenerator generator(parser, path, file_name);
return generator.generate();
}
@@ -1609,9 +1609,8 @@ class KotlinCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+2
View File
@@ -24,6 +24,8 @@ namespace flatbuffers {
// Constructs a new Kotlin code generator.
std::unique_ptr<CodeGenerator> NewKotlinCodeGenerator();
// Constructs a new Kotlin code generator.
std::unique_ptr<CodeGenerator> NewKotlinKMPCodeGenerator();
} // namespace flatbuffers
#endif // FLATBUFFERS_IDL_GEN_KOTLIN_H_
File diff suppressed because it is too large Load Diff
+20 -14
View File
@@ -63,8 +63,10 @@ class LobsterGenerator : public BaseGenerator {
std::string GenTypeName(const Type &type) {
auto bits = NumToString(SizeOf(type.base_type) * 8);
if (IsInteger(type.base_type)) {
if (IsUnsigned(type.base_type)) return "uint" + bits;
else return "int" + bits;
if (IsUnsigned(type.base_type))
return "uint" + bits;
else
return "int" + bits;
}
if (IsFloat(type.base_type)) return "float" + bits;
if (IsString(type)) return "string";
@@ -120,16 +122,17 @@ class LobsterGenerator : public BaseGenerator {
auto defval = field.IsOptional() ? "0" : field.value.constant;
acc = "buf_.flatbuffers_field_" + GenTypeName(field.value.type) +
"(pos_, " + offsets + ", " + defval + ")";
if (IsBool(field.value.type.base_type))
acc = "bool(" + acc + ")";
if (IsBool(field.value.type.base_type)) acc = "bool(" + acc + ")";
}
if (field.value.type.enum_def)
acc = NormalizedName(*field.value.type.enum_def) + "(" + acc + ")";
if (field.IsOptional()) {
acc += ", buf_.flatbuffers_field_present(pos_, " + offsets + ")";
code += def + "() -> " + LobsterType(field.value.type) + ", bool:\n return " + acc + "\n";
code += def + "() -> " + LobsterType(field.value.type) +
", bool:\n return " + acc + "\n";
} else {
code += def + "() -> " + LobsterType(field.value.type) + ":\n return " + acc + "\n";
code += def + "() -> " + LobsterType(field.value.type) +
":\n return " + acc + "\n";
}
return;
}
@@ -150,7 +153,8 @@ class LobsterGenerator : public BaseGenerator {
}
case BASE_TYPE_STRING:
code += def +
"() -> string:\n return buf_.flatbuffers_field_string(pos_, " +
"() -> string:\n return "
"buf_.flatbuffers_field_string(pos_, " +
offsets + ")\n";
break;
case BASE_TYPE_VECTOR: {
@@ -161,7 +165,9 @@ class LobsterGenerator : public BaseGenerator {
if (!(vectortype.struct_def->fixed)) {
start = "buf_.flatbuffers_indirect(" + start + ")";
}
code += def + "(i:int) -> " + NamespacedName(*field.value.type.struct_def) + ":\n return ";
code += def + "(i:int) -> " +
NamespacedName(*field.value.type.struct_def) +
":\n return ";
code += NamespacedName(*field.value.type.struct_def) + " { buf_, " +
start + " }\n";
} else {
@@ -169,7 +175,8 @@ class LobsterGenerator : public BaseGenerator {
code += def + "(i:int) -> string:\n return ";
code += "buf_.flatbuffers_string";
} else {
code += def + "(i:int) -> " + LobsterType(vectortype) + ":\n return ";
code += def + "(i:int) -> " + LobsterType(vectortype) +
":\n return ";
code += "buf_.read_" + GenTypeName(vectortype) + "_le";
}
code += "(buf_.flatbuffers_field_vector(pos_, " + offsets +
@@ -398,8 +405,8 @@ class LobsterGenerator : public BaseGenerator {
} // namespace lobster
bool GenerateLobster(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateLobster(const Parser &parser, const std::string &path,
const std::string &file_name) {
lobster::LobsterGenerator generator(parser, path, file_name);
return generator.generate();
}
@@ -414,9 +421,8 @@ class LobsterCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
-806
View File
@@ -1,806 +0,0 @@
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// independent from idl_parser, since this code is not needed for most clients
#include "idl_gen_lua.h"
#include <string>
#include <unordered_set>
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
namespace lua {
// Hardcode spaces per indentation.
const CommentConfig def_comment = { nullptr, "--", nullptr };
const char *Indent = " ";
const char *Comment = "-- ";
const char *End = "end\n";
const char *EndFunc = "end\n";
const char *SelfData = "self.view";
const char *SelfDataPos = "self.view.pos";
const char *SelfDataBytes = "self.view.bytes";
class LuaGenerator : public BaseGenerator {
public:
LuaGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "" /* not used */,
"" /* not used */, "lua") {
static const char *const keywords[] = {
"and", "break", "do", "else", "elseif", "end", "false", "for",
"function", "goto", "if", "in", "local", "nil", "not", "or",
"repeat", "return", "then", "true", "until", "while"
};
keywords_.insert(std::begin(keywords), std::end(keywords));
}
// Most field accessors need to retrieve and test the field offset first,
// this is the prefix code for that.
std::string OffsetPrefix(const FieldDef &field) {
return std::string(Indent) + "local o = " + SelfData + ":Offset(" +
NumToString(field.value.offset) + ")\n" + Indent +
"if o ~= 0 then\n";
}
// Begin a class declaration.
void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "local " + NormalizedName(struct_def) + " = {} -- the module\n";
code += "local " + NormalizedMetaName(struct_def) +
" = {} -- the class metatable\n";
code += "\n";
}
// Begin enum code with a class declaration.
void BeginEnum(const std::string &class_name, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "local " + class_name + " = {\n";
}
std::string EscapeKeyword(const std::string &name) const {
return keywords_.find(name) == keywords_.end() ? name : "_" + name;
}
std::string NormalizedName(const Definition &definition) const {
return EscapeKeyword(definition.name);
}
std::string NormalizedName(const EnumVal &ev) const {
return EscapeKeyword(ev.name);
}
std::string NormalizedMetaName(const Definition &definition) const {
return EscapeKeyword(definition.name) + "_mt";
}
// A single enum member.
void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += std::string(Indent) + NormalizedName(ev) + " = " +
enum_def.ToString(ev) + ",\n";
}
// End enum code.
void EndEnum(std::string *code_ptr) {
std::string &code = *code_ptr;
code += "}\n";
}
void GenerateNewObjectPrototype(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedName(struct_def) + ".New()\n";
code += std::string(Indent) + "local o = {}\n";
code += std::string(Indent) +
"setmetatable(o, {__index = " + NormalizedMetaName(struct_def) +
"})\n";
code += std::string(Indent) + "return o\n";
code += EndFunc;
}
// Initialize a new struct or table from existing data.
void NewRootTypeFromBuffer(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedName(struct_def) + ".GetRootAs" +
NormalizedName(struct_def) + "(buf, offset)\n";
code += std::string(Indent) + "if type(buf) == \"string\" then\n";
code += std::string(Indent) + Indent +
"buf = flatbuffers.binaryArray.New(buf)\n";
code += std::string(Indent) + "end\n";
code += std::string(Indent) +
"local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n";
code += std::string(Indent) + "local o = " + NormalizedName(struct_def) +
".New()\n";
code += std::string(Indent) + "o:Init(buf, n + offset)\n";
code += std::string(Indent) + "return o\n";
code += EndFunc;
}
// Initialize an existing object with other data, to avoid an allocation.
void InitializeExisting(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
code += "Init(buf, pos)\n";
code +=
std::string(Indent) + SelfData + " = flatbuffers.view.New(buf, pos)\n";
code += EndFunc;
}
// Get the length of a vector.
void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
code +=
ConvertCase(NormalizedName(field), Case::kUpperCamel) + "Length()\n";
code += OffsetPrefix(field);
code +=
std::string(Indent) + Indent + "return " + SelfData + ":VectorLen(o)\n";
code += std::string(Indent) + End;
code += std::string(Indent) + "return 0\n";
code += EndFunc;
}
// Get the value of a struct's scalar.
void GetScalarFieldOfStruct(const StructDef &struct_def,
const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "()\n";
code += std::string(Indent) + "return " + getter;
code += std::string(SelfDataPos) + " + " + NumToString(field.value.offset) +
")\n";
code += EndFunc;
}
// Get the value of a table's scalar.
void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "()\n";
code += OffsetPrefix(field);
getter += std::string("o + ") + SelfDataPos + ")";
auto is_bool = field.value.type.base_type == BASE_TYPE_BOOL;
if (is_bool) { getter = "(" + getter + " ~= 0)"; }
code += std::string(Indent) + Indent + "return " + getter + "\n";
code += std::string(Indent) + End;
std::string default_value;
if (is_bool) {
default_value = field.value.constant == "0" ? "false" : "true";
} else {
default_value = field.value.constant;
}
code += std::string(Indent) + "return " + default_value + "\n";
code += EndFunc;
}
// Get a struct by initializing an existing struct.
// Specific to Struct.
void GetStructFieldOfStruct(const StructDef &struct_def,
const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "(obj)\n";
code += std::string(Indent) + "obj:Init(" + SelfDataBytes + ", " +
SelfDataPos + " + ";
code += NumToString(field.value.offset) + ")\n";
code += std::string(Indent) + "return obj\n";
code += EndFunc;
}
// Get a struct by initializing an existing struct.
// Specific to Table.
void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "()\n";
code += OffsetPrefix(field);
if (field.value.type.struct_def->fixed) {
code +=
std::string(Indent) + Indent + "local x = o + " + SelfDataPos + "\n";
} else {
code += std::string(Indent) + Indent + "local x = " + SelfData +
":Indirect(o + " + SelfDataPos + ")\n";
}
code += std::string(Indent) + Indent + "local obj = require('" +
TypeNameWithNamespace(field) + "').New()\n";
code +=
std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
code += std::string(Indent) + Indent + "return obj\n";
code += std::string(Indent) + End;
code += EndFunc;
}
// Get the value of a string.
void GetStringField(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "()\n";
code += OffsetPrefix(field);
code +=
std::string(Indent) + Indent + "return " + GenGetter(field.value.type);
code += std::string("o + ") + SelfDataPos + ")\n";
code += std::string(Indent) + End;
code += EndFunc;
}
// Get the value of a union from an object.
void GetUnionField(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
code += ConvertCase(NormalizedName(field), Case::kUpperCamel) + "()\n";
code += OffsetPrefix(field);
// TODO(rw): this works and is not the good way to it:
// bool is_native_table = TypeName(field) == "*flatbuffers.Table";
// if (is_native_table) {
// code += std::string(Indent) + Indent + "from flatbuffers.table import
// Table\n";
//} else {
// code += std::string(Indent) + Indent +
// code += "from ." + TypeName(field) + " import " + TypeName(field) +
// "\n";
//}
code +=
std::string(Indent) + Indent +
"local obj = "
"flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)\n";
code += std::string(Indent) + Indent + GenGetter(field.value.type) +
"obj, o)\n";
code += std::string(Indent) + Indent + "return obj\n";
code += std::string(Indent) + End;
code += EndFunc;
}
// Get the value of a vector's struct member.
void GetMemberOfVectorOfStruct(const StructDef &struct_def,
const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "(j)\n";
code += OffsetPrefix(field);
code +=
std::string(Indent) + Indent + "local x = " + SelfData + ":Vector(o)\n";
code += std::string(Indent) + Indent + "x = x + ((j-1) * ";
code += NumToString(InlineSize(vectortype)) + ")\n";
if (!(vectortype.struct_def->fixed)) {
code +=
std::string(Indent) + Indent + "x = " + SelfData + ":Indirect(x)\n";
}
code += std::string(Indent) + Indent + "local obj = require('" +
TypeNameWithNamespace(field) + "').New()\n";
code +=
std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
code += std::string(Indent) + Indent + "return obj\n";
code += std::string(Indent) + End;
code += EndFunc;
}
// Get the value of a vector's non-struct member. Uses a named return
// argument to conveniently set the zero value for the result.
void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "(j)\n";
code += OffsetPrefix(field);
code +=
std::string(Indent) + Indent + "local a = " + SelfData + ":Vector(o)\n";
code += std::string(Indent) + Indent;
code += "return " + GenGetter(field.value.type);
code += "a + ((j-1) * ";
code += NumToString(InlineSize(vectortype)) + "))\n";
code += std::string(Indent) + End;
if (IsString(vectortype)) {
code += std::string(Indent) + "return ''\n";
} else {
code += std::string(Indent) + "return 0\n";
}
code += EndFunc;
}
// Access a byte/ubyte vector as a string
void AccessByteVectorAsString(const StructDef &struct_def,
const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "AsString(start, stop)\n";
code += std::string(Indent) + "return " + SelfData + ":VectorAsString(" +
NumToString(field.value.offset) + ", start, stop)\n";
code += EndFunc;
}
// Begin the creator function signature.
void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedName(struct_def) + ".Create" +
NormalizedName(struct_def);
code += "(builder";
}
// Recursively generate arguments for a constructor, to deal with nested
// structs.
void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix,
std::string *code_ptr) {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (IsStruct(field.value.type)) {
// Generate arguments for a struct inside a struct. To ensure names
// don't clash, and to make it obvious these arguments are constructing
// a nested struct, prefix the name with the field name.
StructBuilderArgs(*field.value.type.struct_def,
(nameprefix + (NormalizedName(field) + "_")).c_str(),
code_ptr);
} else {
std::string &code = *code_ptr;
code += std::string(", ") + nameprefix;
code += ConvertCase(NormalizedName(field), Case::kLowerCamel);
}
}
}
// End the creator function signature.
void EndBuilderArgs(std::string *code_ptr) {
std::string &code = *code_ptr;
code += ")\n";
}
// Recursively generate struct construction statements and instert manual
// padding.
void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += std::string(Indent) + "builder:Prep(" +
NumToString(struct_def.minalign) + ", ";
code += NumToString(struct_def.bytesize) + ")\n";
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it;
if (field.padding)
code += std::string(Indent) + "builder:Pad(" +
NumToString(field.padding) + ")\n";
if (IsStruct(field.value.type)) {
StructBuilderBody(*field.value.type.struct_def,
(nameprefix + (NormalizedName(field) + "_")).c_str(),
code_ptr);
} else {
code +=
std::string(Indent) + "builder:Prepend" + GenMethod(field) + "(";
code += nameprefix +
ConvertCase(NormalizedName(field), Case::kLowerCamel) + ")\n";
}
}
}
void EndBuilderBody(std::string *code_ptr) {
std::string &code = *code_ptr;
code += std::string(Indent) + "return builder:Offset()\n";
code += EndFunc;
}
// Get the value of a table's starting offset.
void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedName(struct_def) + ".Start";
code += "(builder) ";
code += "builder:StartObject(";
code += NumToString(struct_def.fields.vec.size());
code += ") end\n";
}
// Set the value of a table's field.
void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
const size_t offset, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedName(struct_def) + ".Add" +
ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "(builder, ";
code += ConvertCase(NormalizedName(field), Case::kLowerCamel);
code += ") ";
code += "builder:Prepend";
code += GenMethod(field) + "Slot(";
code += NumToString(offset) + ", ";
// todo: i don't need to cast in Lua, but am I missing something?
// if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
// code += "flatbuffers.N.UOffsetTFlags.py_type";
// code += "(";
// code += ConvertCase(NormalizedName(field), Case::kLowerCamel) + ")";
// } else {
code += ConvertCase(NormalizedName(field), Case::kLowerCamel);
// }
code += ", " + field.value.constant;
code += ") end\n";
}
// Set the value of one of the members of a table's vector.
void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedName(struct_def) + ".Start";
code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "Vector(builder, numElems) return builder:StartVector(";
auto vector_type = field.value.type.VectorType();
auto alignment = InlineAlignment(vector_type);
auto elem_size = InlineSize(vector_type);
code += NumToString(elem_size);
code += ", numElems, " + NumToString(alignment);
code += ") end\n";
}
// Get the offset of the end of a table.
void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedName(struct_def) + ".End";
code += "(builder) ";
code += "return builder:EndObject() end\n";
}
// Generate the receiver for function signatures.
void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedMetaName(struct_def) + ":";
}
// Generate a struct field, conditioned on its child type(s).
void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) {
GenComment(field.doc_comment, code_ptr, &def_comment);
if (IsScalar(field.value.type.base_type)) {
if (struct_def.fixed) {
GetScalarFieldOfStruct(struct_def, field, code_ptr);
} else {
GetScalarFieldOfTable(struct_def, field, code_ptr);
}
} else {
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT:
if (struct_def.fixed) {
GetStructFieldOfStruct(struct_def, field, code_ptr);
} else {
GetStructFieldOfTable(struct_def, field, code_ptr);
}
break;
case BASE_TYPE_STRING:
GetStringField(struct_def, field, code_ptr);
break;
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_STRUCT) {
GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
} else {
GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
if (vectortype.base_type == BASE_TYPE_CHAR ||
vectortype.base_type == BASE_TYPE_UCHAR) {
AccessByteVectorAsString(struct_def, field, code_ptr);
}
}
break;
}
case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
default: FLATBUFFERS_ASSERT(0);
}
}
if (IsVector(field.value.type)) {
GetVectorLen(struct_def, field, code_ptr);
}
}
// Generate table constructors, conditioned on its members' types.
void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
GetStartOfTable(struct_def, code_ptr);
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto offset = it - struct_def.fields.vec.begin();
BuildFieldOfTable(struct_def, field, offset, code_ptr);
if (IsVector(field.value.type)) {
BuildVectorOfTable(struct_def, field, code_ptr);
}
}
GetEndOffsetOnTable(struct_def, code_ptr);
}
// Generate struct or table methods.
void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
if (struct_def.generated) return;
GenComment(struct_def.doc_comment, code_ptr, &def_comment);
BeginClass(struct_def, code_ptr);
GenerateNewObjectPrototype(struct_def, code_ptr);
if (!struct_def.fixed) {
// Generate a special accessor for the table that has been declared as
// the root type.
NewRootTypeFromBuffer(struct_def, code_ptr);
}
// Generate the Init method that sets the field in a pre-existing
// accessor object. This is to allow object reuse.
InitializeExisting(struct_def, code_ptr);
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
GenStructAccessor(struct_def, field, code_ptr);
}
if (struct_def.fixed) {
// create a struct constructor function
GenStructBuilder(struct_def, code_ptr);
} else {
// Create a set of functions that allow table construction.
GenTableBuilders(struct_def, code_ptr);
}
}
// Generate enum declarations.
void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
if (enum_def.generated) return;
GenComment(enum_def.doc_comment, code_ptr, &def_comment);
BeginEnum(NormalizedName(enum_def), code_ptr);
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
GenComment(ev.doc_comment, code_ptr, &def_comment, Indent);
EnumMember(enum_def, ev, code_ptr);
}
EndEnum(code_ptr);
}
// Returns the function name that is able to read a value of the given type.
std::string GenGetter(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_STRING: return std::string(SelfData) + ":String(";
case BASE_TYPE_UNION: return std::string(SelfData) + ":Union(";
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
default:
return std::string(SelfData) + ":Get(flatbuffers.N." +
ConvertCase(GenTypeGet(type), Case::kUpperCamel) + ", ";
}
}
// Returns the method name for use with add/put calls.
std::string GenMethod(const FieldDef &field) {
return IsScalar(field.value.type.base_type)
? ConvertCase(GenTypeBasic(field.value.type), Case::kUpperCamel)
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
}
std::string GenTypeBasic(const Type &type) {
// clang-format off
static const char *ctypename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \
#PTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
};
// clang-format on
return ctypename[type.base_type];
}
std::string GenTypePointer(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_STRING: return "string";
case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
case BASE_TYPE_STRUCT: return type.struct_def->name;
case BASE_TYPE_UNION:
// fall through
default: return "*flatbuffers.Table";
}
}
std::string GenTypeGet(const Type &type) {
return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
}
std::string GetNamespace(const Type &type) {
return type.struct_def->defined_namespace->GetFullyQualifiedName(
type.struct_def->name);
}
std::string TypeName(const FieldDef &field) {
return GenTypeGet(field.value.type);
}
std::string TypeNameWithNamespace(const FieldDef &field) {
return GetNamespace(field.value.type);
}
// Create a struct with a builder and the struct's arguments.
void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) {
BeginBuilderArgs(struct_def, code_ptr);
StructBuilderArgs(struct_def, "", code_ptr);
EndBuilderArgs(code_ptr);
StructBuilderBody(struct_def, "", code_ptr);
EndBuilderBody(code_ptr);
}
bool generate() {
if (!generateEnums()) return false;
if (!generateStructs()) return false;
return true;
}
private:
bool generateEnums() {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
auto &enum_def = **it;
std::string enumcode;
GenEnum(enum_def, &enumcode);
if (!SaveType(enum_def, enumcode, false)) return false;
}
return true;
}
bool generateStructs() {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
std::string declcode;
GenStruct(struct_def, &declcode);
if (!SaveType(struct_def, declcode, true)) return false;
}
return true;
}
// Begin by declaring namespace and imports.
void BeginFile(const std::string &name_space_name, const bool needs_imports,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += std::string(Comment) + FlatBuffersGeneratedWarning() + "\n\n";
code += std::string(Comment) + "namespace: " + name_space_name + "\n\n";
if (needs_imports) {
code += "local flatbuffers = require('flatbuffers')\n\n";
}
}
// Save out the generated code for a Lua Table type.
bool SaveType(const Definition &def, const std::string &classcode,
bool needs_imports) {
if (!classcode.length()) return true;
std::string namespace_dir = path_;
auto &namespaces = def.defined_namespace->components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
if (it != namespaces.begin()) namespace_dir += kPathSeparator;
namespace_dir += *it;
// std::string init_py_filename = namespace_dir + "/__init__.py";
// SaveFile(init_py_filename.c_str(), "", false);
}
std::string code = "";
BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
code += classcode;
code += "\n";
code +=
"return " + NormalizedName(def) + " " + Comment + "return the module";
std::string filename =
NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".lua";
return SaveFile(filename.c_str(), code, false);
}
private:
std::unordered_set<std::string> keywords_;
};
} // namespace lua
bool GenerateLua(const Parser &parser, const std::string &path,
const std::string &file_name) {
lua::LuaGenerator generator(parser, path, file_name);
return generator.generate();
}
namespace {
class LuaCodeGenerator : public CodeGenerator {
public:
Status GenerateCode(const Parser &parser, const std::string &path,
const std::string &filename) override {
if (!GenerateLua(parser, path, filename)) { return Status::ERROR; }
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
return Status::NOT_IMPLEMENTED;
}
Status GenerateMakeRule(const Parser &parser, const std::string &path,
const std::string &filename,
std::string &output) override {
(void)parser;
(void)path;
(void)filename;
(void)output;
return Status::NOT_IMPLEMENTED;
}
Status GenerateGrpcCode(const Parser &parser, const std::string &path,
const std::string &filename) override {
(void)parser;
(void)path;
(void)filename;
return Status::NOT_IMPLEMENTED;
}
Status GenerateRootFile(const Parser &parser,
const std::string &path) override {
(void)parser;
(void)path;
return Status::NOT_IMPLEMENTED;
}
bool IsSchemaOnly() const override { return true; }
bool SupportsBfbsGeneration() const override { return true; }
bool SupportsRootFileGeneration() const override { return false; }
IDLOptions::Language Language() const override { return IDLOptions::kLua; }
std::string LanguageName() const override { return "Lua"; }
};
} // namespace
std::unique_ptr<CodeGenerator> NewLuaCodeGenerator() {
return std::unique_ptr<LuaCodeGenerator>(new LuaCodeGenerator());
}
} // namespace flatbuffers
-29
View File
@@ -1,29 +0,0 @@
/*
* Copyright 2023 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FLATBUFFERS_IDL_GEN_LUA_H_
#define FLATBUFFERS_IDL_GEN_LUA_H_
#include "flatbuffers/code_generator.h"
namespace flatbuffers {
// Constructs a new Lua code generator.
std::unique_ptr<CodeGenerator> NewLuaCodeGenerator();
} // namespace flatbuffers
#endif // FLATBUFFERS_IDL_GEN_LUA_H_
+4 -5
View File
@@ -939,8 +939,8 @@ class PhpGenerator : public BaseGenerator {
};
} // namespace php
bool GeneratePhp(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GeneratePhp(const Parser &parser, const std::string &path,
const std::string &file_name) {
php::PhpGenerator generator(parser, path, file_name);
return generator.generate();
}
@@ -955,9 +955,8 @@ class PhpCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+90 -80
View File
@@ -74,7 +74,7 @@ static Namer::Config PythonDefaultConfig() {
static const CommentConfig def_comment = { nullptr, "#", nullptr };
static const std::string Indent = " ";
} // namespace
} // namespace
class PythonGenerator : public BaseGenerator {
public:
@@ -149,10 +149,11 @@ class PythonGenerator : public BaseGenerator {
if (!parser_.opts.python_no_type_prefix_suffix) {
// Add an alias with the old name
code += Indent + "@classmethod\n";
code += Indent + "def GetRootAs" + struct_type + "(cls, buf, offset=0):\n";
code +=
Indent + Indent +
"\"\"\"This method is deprecated. Please switch to GetRootAs.\"\"\"\n";
Indent + "def GetRootAs" + struct_type + "(cls, buf, offset=0):\n";
code += Indent + Indent +
"\"\"\"This method is deprecated. Please switch to "
"GetRootAs.\"\"\"\n";
code += Indent + Indent + "return cls.GetRootAs(buf, offset)\n";
}
}
@@ -179,16 +180,15 @@ class PythonGenerator : public BaseGenerator {
GenReceiver(struct_def, code_ptr);
code += namer_.Method(field) + "Length(self)";
if (parser_.opts.python_typing) {
code += " -> int";
}
if (parser_.opts.python_typing) { code += " -> int"; }
code += ":";
if(!IsArray(field.value.type)){
code += OffsetPrefix(field,false);
if (!IsArray(field.value.type)) {
code += OffsetPrefix(field, false);
code += GenIndents(3) + "return self._tab.VectorLen(o)";
code += GenIndents(2) + "return 0\n\n";
}else{
code += GenIndents(2) + "return "+NumToString(field.value.type.fixed_length)+"\n\n";
} else {
code += GenIndents(2) + "return " +
NumToString(field.value.type.fixed_length) + "\n\n";
}
}
@@ -199,17 +199,15 @@ class PythonGenerator : public BaseGenerator {
GenReceiver(struct_def, code_ptr);
code += namer_.Method(field) + "IsNone(self)";
if (parser_.opts.python_typing) {
code += " -> bool";
}
if (parser_.opts.python_typing) { code += " -> bool"; }
code += ":";
if(!IsArray(field.value.type)){
if (!IsArray(field.value.type)) {
code += GenIndents(2) +
"o = flatbuffers.number_types.UOffsetTFlags.py_type" +
"(self._tab.Offset(" + NumToString(field.value.offset) + "))";
code += GenIndents(2) + "return o == 0";
} else {
//assume that we always have an array as memory is preassigned
// assume that we always have an array as memory is preassigned
code += GenIndents(2) + "return False";
}
code += "\n\n";
@@ -277,7 +275,7 @@ class PythonGenerator : public BaseGenerator {
code += namer_.Method(field);
const ImportMapEntry import_entry = {
"." + GenPackageReference(field.value.type), TypeName(field)
GenPackageReference(field.value.type), TypeName(field)
};
if (parser_.opts.python_typing) {
@@ -290,7 +288,8 @@ class PythonGenerator : public BaseGenerator {
code += "(self, i):";
}
if (parser_.opts.include_dependence_headers && !parser_.opts.python_typing) {
if (parser_.opts.include_dependence_headers &&
!parser_.opts.python_typing) {
code += GenIndents(2);
code += "from " + import_entry.first + " import " + import_entry.second +
"\n";
@@ -317,8 +316,9 @@ class PythonGenerator : public BaseGenerator {
code += NumToString(field.value.offset) + " + i * ";
code += NumToString(InlineSize(field.value.type.VectorType()));
code += ")) for i in range(";
code += "self."+namer_.Method(field)+"Length()" + ")]";
code += GenIndents(2) +"elif j >= 0 and j < self."+namer_.Method(field)+"Length():";
code += "self." + namer_.Method(field) + "Length()" + ")]";
code += GenIndents(2) + "elif j >= 0 and j < self." + namer_.Method(field) +
"Length():";
code += GenIndents(3) + "return " + GenGetter(field.value.type);
code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
code += NumToString(field.value.offset) + " + j * ";
@@ -337,7 +337,7 @@ class PythonGenerator : public BaseGenerator {
code += namer_.Method(field) + "(self)";
const ImportMapEntry import_entry = {
"." + GenPackageReference(field.value.type), TypeName(field)
GenPackageReference(field.value.type), TypeName(field)
};
if (parser_.opts.python_typing) {
@@ -355,7 +355,8 @@ class PythonGenerator : public BaseGenerator {
code += "x = self._tab.Indirect(o + self._tab.Pos)\n";
}
if (parser_.opts.include_dependence_headers && !parser_.opts.python_typing) {
if (parser_.opts.include_dependence_headers &&
!parser_.opts.python_typing) {
code += Indent + Indent + Indent;
code += "from " + import_entry.first + " import " + import_entry.second +
"\n";
@@ -445,7 +446,7 @@ class PythonGenerator : public BaseGenerator {
GenReceiver(struct_def, code_ptr);
code += namer_.Method(field);
const ImportMapEntry import_entry = {
"." + GenPackageReference(field.value.type), TypeName(field)
GenPackageReference(field.value.type), TypeName(field)
};
if (parser_.opts.python_typing) {
@@ -464,7 +465,8 @@ class PythonGenerator : public BaseGenerator {
if (!(vectortype.struct_def->fixed)) {
code += Indent + Indent + Indent + "x = self._tab.Indirect(x)\n";
}
if (parser_.opts.include_dependence_headers && !parser_.opts.python_typing) {
if (parser_.opts.include_dependence_headers &&
!parser_.opts.python_typing) {
code += Indent + Indent + Indent;
code += "from " + import_entry.first + " import " + import_entry.second +
"\n";
@@ -519,7 +521,7 @@ class PythonGenerator : public BaseGenerator {
GenReceiver(struct_def, code_ptr);
code += namer_.Method(field) + "AsNumpy(self):";
if(!IsArray(field.value.type)){
if (!IsArray(field.value.type)) {
code += OffsetPrefix(field, false);
code += GenIndents(3);
@@ -533,11 +535,13 @@ class PythonGenerator : public BaseGenerator {
} else {
code += GenIndents(2) + "return 0\n";
}
}else{
} else {
code += GenIndents(2) + "return ";
code += "self._tab.GetArrayAsNumpy(flatbuffers.number_types.";
code += namer_.Method(GenTypeGet(field.value.type.VectorType()));
code += "Flags, self._tab.Pos + "+NumToString(field.value.offset)+", "+NumToString("self."+namer_.Method(field)+"Length()")+")\n";
code += "Flags, self._tab.Pos + " + NumToString(field.value.offset) +
", " + NumToString("self." + namer_.Method(field) + "Length()") +
")\n";
}
code += "\n";
}
@@ -564,11 +568,9 @@ class PythonGenerator : public BaseGenerator {
const std::string unqualified_name = nested->constant;
std::string qualified_name = NestedFlatbufferType(unqualified_name);
if (qualified_name.empty()) {
qualified_name = nested->constant;
}
if (qualified_name.empty()) { qualified_name = nested->constant; }
const ImportMapEntry import_entry = { "." + qualified_name,
const ImportMapEntry import_entry = { qualified_name,
unqualified_name };
auto &code = *code_ptr;
@@ -704,7 +706,9 @@ class PythonGenerator : public BaseGenerator {
const auto struct_type = namer_.Type(struct_def);
// Generate method with struct name.
const auto name = parser_.opts.python_no_type_prefix_suffix ? "Start" : struct_type + "Start";
const auto name = parser_.opts.python_no_type_prefix_suffix
? "Start"
: struct_type + "Start";
code += "def " + name;
if (parser_.opts.python_typing) {
@@ -736,12 +740,14 @@ class PythonGenerator : public BaseGenerator {
const std::string field_method = namer_.Method(field);
const std::string field_ty = GenFieldTy(field);
const auto name = parser_.opts.python_no_type_prefix_suffix ? "Add" + field_method : namer_.Type(struct_def) + "Add" + field_method;
const auto name = parser_.opts.python_no_type_prefix_suffix
? "Add" + field_method
: namer_.Type(struct_def) + "Add" + field_method;
// Generate method with struct name.
code += "def " + name;
if (parser_.opts.python_typing) {
code += "(builder: flatbuffers.Builder, " + field_var + ": " + field_ty;
code += "(builder: flatbuffers.Builder, " + field_var + ": " + field_ty;
} else {
code += "(builder, " + field_var;
}
@@ -767,9 +773,14 @@ class PythonGenerator : public BaseGenerator {
if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
// Generate method without struct name.
code += "def Add" + field_method + "(builder: flatbuffers.Builder, " + field_var + ": " + field_ty + "):\n";
code +=
Indent + namer_.Type(struct_def) + "Add" + field_method;
code += "def Add" + field_method;
if (parser_.opts.python_typing) {
code += "(builder: flatbuffers.Builder, " + field_var + ": " + field_ty;
} else {
code += "(builder, " + field_var;
}
code += "):\n";
code += Indent + namer_.Type(struct_def) + "Add" + field_method;
code += "(builder, ";
code += field_var;
code += ")\n\n";
@@ -784,7 +795,9 @@ class PythonGenerator : public BaseGenerator {
const std::string field_method = namer_.Method(field);
// Generate method with struct name.
const auto name = parser_.opts.python_no_type_prefix_suffix ? "Start" + field_method : struct_type + "Start" + field_method;
const auto name = parser_.opts.python_no_type_prefix_suffix
? "Start" + field_method
: struct_type + "Start" + field_method;
code += "def " + name;
if (parser_.opts.python_typing) {
code += "Vector(builder, numElems: int) -> int:\n";
@@ -802,7 +815,8 @@ class PythonGenerator : public BaseGenerator {
if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
// Generate method without struct name.
code += "def Start" + field_method + "Vector(builder, numElems: int) -> int:\n";
code += "def Start" + field_method +
"Vector(builder, numElems: int) -> int:\n";
code += Indent + "return " + struct_type + "Start";
code += field_method + "Vector(builder, numElems)\n\n";
}
@@ -849,7 +863,9 @@ class PythonGenerator : public BaseGenerator {
std::string *code_ptr) const {
auto &code = *code_ptr;
const auto name = parser_.opts.python_no_type_prefix_suffix ? "End" : namer_.Type(struct_def) + "End";
const auto name = parser_.opts.python_no_type_prefix_suffix
? "End"
: namer_.Type(struct_def) + "End";
// Generate method with struct name.
if (parser_.opts.python_typing) {
code += "def " + name + "(builder: flatbuffers.Builder) -> int:\n";
@@ -921,7 +937,9 @@ class PythonGenerator : public BaseGenerator {
}
break;
}
case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr, imports); break;
case BASE_TYPE_UNION:
GetUnionField(struct_def, field, code_ptr, imports);
break;
default: FLATBUFFERS_ASSERT(0);
}
}
@@ -1255,14 +1273,15 @@ class PythonGenerator : public BaseGenerator {
}
void InitializeFromPackedBuf(const StructDef &struct_def,
std::string *code_ptr) const {
std::string *code_ptr) const {
auto &code = *code_ptr;
const auto struct_var = namer_.Variable(struct_def);
const auto struct_type = namer_.Type(struct_def);
code += GenIndents(1) + "@classmethod";
code += GenIndents(1) + "def InitFromPackedBuf(cls, buf, pos=0):";
code += GenIndents(2) + "n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)";
code += GenIndents(2) +
"n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)";
code += GenIndents(2) + "return cls.InitFromBuf(buf, pos+n)";
code += "\n";
}
@@ -1281,20 +1300,21 @@ class PythonGenerator : public BaseGenerator {
code += "\n";
}
void GenCompareOperator(const StructDef &struct_def,
void GenCompareOperator(const StructDef &struct_def,
std::string *code_ptr) const {
auto &code = *code_ptr;
code += GenIndents(1) + "def __eq__(self, other):";
code += GenIndents(2) + "return type(self) == type(other)";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
// Wrties the comparison statement for this field.
const auto field_field = namer_.Field(field);
code += " and \\" + GenIndents(3) + "self." + field_field + " == " + "other." + field_field;
}
// Wrties the comparison statement for this field.
const auto field_field = namer_.Field(field);
code += " and \\" + GenIndents(3) + "self." + field_field +
" == " + "other." + field_field;
}
code += "\n";
}
@@ -1317,8 +1337,9 @@ class PythonGenerator : public BaseGenerator {
code += field_type + "()";
}
code += ") is not None:";
code += GenIndents(3) + "self." + field_field + " = " + namer_.ObjectType(field_type) +
+ ".InitFromObj(" + struct_var + "." + field_method + "(";
code += GenIndents(3) + "self." + field_field + " = " +
namer_.ObjectType(field_type) + +".InitFromObj(" + struct_var +
"." + field_method + "(";
// A struct's accessor requires a struct buf instance.
if (struct_def.fixed && field.value.type.base_type == BASE_TYPE_STRUCT) {
code += field_type + "()";
@@ -1368,8 +1389,9 @@ class PythonGenerator : public BaseGenerator {
"(i) is None:";
code += GenIndents(5) + "self." + field_field + ".append(None)";
code += GenIndents(4) + "else:";
code += GenIndents(5) + one_instance + " = " + namer_.ObjectType(field_type) +
".InitFromObj(" + struct_var + "." + field_method + "(i))";
code += GenIndents(5) + one_instance + " = " +
namer_.ObjectType(field_type) + ".InitFromObj(" + struct_var + "." +
field_method + "(i))";
code +=
GenIndents(5) + "self." + field_field + ".append(" + one_instance + ")";
}
@@ -1399,8 +1421,9 @@ class PythonGenerator : public BaseGenerator {
"(i) is None:";
code += GenIndents(5) + "self." + field_field + ".append(None)";
code += GenIndents(4) + "else:";
code += GenIndents(5) + one_instance + " = " + namer_.ObjectType(field_type) +
".InitFromObj(" + struct_var + "." + field_method + "(i))";
code += GenIndents(5) + one_instance + " = " +
namer_.ObjectType(field_type) + ".InitFromObj(" + struct_var + "." +
field_method + "(i))";
code +=
GenIndents(5) + "self." + field_field + ".append(" + one_instance + ")";
}
@@ -1780,9 +1803,7 @@ class PythonGenerator : public BaseGenerator {
InitializeFromObjForObject(struct_def, &code);
if (parser_.opts.gen_compare) {
GenCompareOperator(struct_def, &code);
}
if (parser_.opts.gen_compare) { GenCompareOperator(struct_def, &code); }
GenUnPack(struct_def, &code);
@@ -1891,17 +1912,11 @@ class PythonGenerator : public BaseGenerator {
std::string GenFieldTy(const FieldDef &field) const {
if (IsScalar(field.value.type.base_type) || IsArray(field.value.type)) {
const std::string ty = GenTypeBasic(field.value.type);
if (ty.find("int") != std::string::npos) {
return "int";
}
if (ty.find("int") != std::string::npos) { return "int"; }
if (ty.find("float") != std::string::npos) {
return "float";
}
if (ty.find("float") != std::string::npos) { return "float"; }
if (ty == "bool") {
return "bool";
}
if (ty == "bool") { return "bool"; }
return "Any";
} else {
@@ -2052,13 +2067,9 @@ class PythonGenerator : public BaseGenerator {
}
if (parser_.opts.one_file) {
if (!declcode.empty()) {
*one_file_code += declcode + "\n\n";
}
if (!declcode.empty()) { *one_file_code += declcode + "\n\n"; }
for (auto import_str: imports) {
one_file_imports.insert(import_str);
}
for (auto import_str : imports) { one_file_imports.insert(import_str); }
} else {
const std::string mod =
namer_.File(struct_def, SkipFile::SuffixAndExtension);
@@ -2135,8 +2146,8 @@ class PythonGenerator : public BaseGenerator {
} // namespace python
bool GeneratePython(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GeneratePython(const Parser &parser, const std::string &path,
const std::string &file_name) {
python::PythonGenerator generator(parser, path, file_name);
return generator.generate();
}
@@ -2151,9 +2162,8 @@ class PythonCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+69 -40
View File
@@ -277,10 +277,10 @@ static bool IsBitFlagsEnum(const EnumDef &enum_def) {
static bool IsOptionalToBuilder(const FieldDef &field) {
return field.IsOptional() || !IsScalar(field.value.type.base_type);
}
} // namespace
} // namespace
bool GenerateRustModuleRootFile(const Parser &parser,
const std::string &output_dir) {
static bool GenerateRustModuleRootFile(const Parser &parser,
const std::string &output_dir) {
if (!parser.opts.rust_module_root_file) {
// Don't generate a root file when generating one file. This isn't an error
// so return true.
@@ -708,7 +708,7 @@ class RustGenerator : public BaseGenerator {
// and an enum array of values
void GenEnum(const EnumDef &enum_def) {
const bool is_private = parser_.opts.no_leak_private_annotations &&
(enum_def.attributes.Lookup("private") != nullptr);
(enum_def.attributes.Lookup("private") != nullptr);
code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
code_.SetValue("ENUM_TY", namer_.Type(enum_def));
code_.SetValue("BASE_TYPE", GetEnumTypeForDecl(enum_def.underlying_type));
@@ -842,15 +842,21 @@ class RustGenerator : public BaseGenerator {
code_ += " type Inner = Self;";
code_ += " #[inline]";
code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
code_ += " let b = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc);";
code_ +=
" let b = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc);";
if (IsBitFlagsEnum(enum_def)) {
// Safety:
// This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.
// from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0
// This is safe because we know bitflags is implemented with a repr
// transparent uint of the correct size. from_bits_unchecked will be
// replaced by an equivalent but safe from_bits_retain in bitflags 2.0
// https://github.com/bitflags/bitflags/issues/262
code_ += " // Safety:";
code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.";
code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0";
code_ +=
" // This is safe because we know bitflags is implemented with a "
"repr transparent uint of the correct size.";
code_ +=
" // from_bits_unchecked will be replaced by an equivalent but "
"safe from_bits_retain in bitflags 2.0";
code_ += " // https://github.com/bitflags/bitflags/issues/262";
code_ += " Self::from_bits_unchecked(b)";
} else {
@@ -863,7 +869,9 @@ class RustGenerator : public BaseGenerator {
code_ += " type Output = {{ENUM_TY}};";
code_ += " #[inline]";
code_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {";
code_ += " flatbuffers::emplace_scalar::<{{BASE_TYPE}}>(dst, {{INTO_BASE}});";
code_ +=
" flatbuffers::emplace_scalar::<{{BASE_TYPE}}>(dst, "
"{{INTO_BASE}});";
code_ += " }";
code_ += "}";
code_ += "";
@@ -879,12 +887,17 @@ class RustGenerator : public BaseGenerator {
code_ += " let b = {{BASE_TYPE}}::from_le(v);";
if (IsBitFlagsEnum(enum_def)) {
// Safety:
// This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.
// from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0
// This is safe because we know bitflags is implemented with a repr
// transparent uint of the correct size. from_bits_unchecked will be
// replaced by an equivalent but safe from_bits_retain in bitflags 2.0
// https://github.com/bitflags/bitflags/issues/262
code_ += " // Safety:";
code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.";
code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0";
code_ +=
" // This is safe because we know bitflags is implemented with a "
"repr transparent uint of the correct size.";
code_ +=
" // from_bits_unchecked will be replaced by an equivalent but "
"safe from_bits_retain in bitflags 2.0";
code_ += " // https://github.com/bitflags/bitflags/issues/262";
code_ += " unsafe { Self::from_bits_unchecked(b) }";
} else {
@@ -1458,7 +1471,8 @@ class RustGenerator : public BaseGenerator {
case ftVectorOfBool:
case ftVectorOfFloat: {
const auto typname = GetTypeBasic(type.VectorType());
return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">");
return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname +
">");
}
case ftVectorOfEnumKey: {
const auto typname = WrapInNameSpace(*type.enum_def);
@@ -1467,7 +1481,8 @@ class RustGenerator : public BaseGenerator {
}
case ftVectorOfStruct: {
const auto typname = WrapInNameSpace(*type.struct_def);
return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">");
return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname +
">");
}
case ftVectorOfTable: {
const auto typname = WrapInNameSpace(*type.struct_def);
@@ -1585,8 +1600,9 @@ class RustGenerator : public BaseGenerator {
: "None";
const std::string unwrap = field.IsOptional() ? "" : ".unwrap()";
return "unsafe { self._tab.get::<" + typname + ">({{STRUCT_TY}}::" + vt_offset +
", " + default_value + ")" + unwrap + "}";
return "unsafe { self._tab.get::<" + typname +
">({{STRUCT_TY}}::" + vt_offset + ", " + default_value + ")" +
unwrap + "}";
}
// Generates a fully-qualified name getter for use with --gen-name-strings
@@ -1646,8 +1662,8 @@ class RustGenerator : public BaseGenerator {
// Generate an accessor struct, builder struct, and create function for a
// table.
void GenTable(const StructDef &struct_def) {
const bool is_private = parser_.opts.no_leak_private_annotations &&
const bool is_private =
parser_.opts.no_leak_private_annotations &&
(struct_def.attributes.Lookup("private") != nullptr);
code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
code_.SetValue("STRUCT_TY", namer_.Type(struct_def));
@@ -1933,13 +1949,17 @@ class RustGenerator : public BaseGenerator {
code_ += " // Safety:";
code_ += " // Created from a valid Table for this object";
code_ += " // Which contains a valid union in this slot";
code_ += " Some(unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(u) })";
code_ +=
" Some(unsafe { "
"{{U_ELEMENT_TABLE_TYPE}}::init_from_table(u) })";
} else {
code_ +=" self.{{FIELD}}().map(|t| {";
code_ += " self.{{FIELD}}().map(|t| {";
code_ += " // Safety:";
code_ += " // Created from a valid Table for this object";
code_ += " // Which contains a valid union in this slot";
code_ += " unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(t) }";
code_ +=
" unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(t) "
"}";
code_ += " })";
}
code_ += " } else {";
@@ -2264,7 +2284,8 @@ class RustGenerator : public BaseGenerator {
case ftUnionValue: {
code_.SetValue("ENUM_METHOD",
namer_.Method(*field.value.type.enum_def));
code_.SetValue("DISCRIMINANT", namer_.LegacyRustUnionTypeMethod(field));
code_.SetValue("DISCRIMINANT",
namer_.LegacyRustUnionTypeMethod(field));
code_ +=
" let {{DISCRIMINANT}} = "
"self.{{FIELD}}.{{ENUM_METHOD}}_type();";
@@ -2312,10 +2333,10 @@ class RustGenerator : public BaseGenerator {
// TODO(cneo): create_vector* should be more generic to avoid
// allocations.
MapNativeTableField(
field,
"let w: Vec<_> = x.iter().map(|s| _fbb.create_string(s)).collect();"
"_fbb.create_vector(&w)");
MapNativeTableField(field,
"let w: Vec<_> = x.iter().map(|s| "
"_fbb.create_string(s)).collect();"
"_fbb.create_vector(&w)");
return;
}
case ftVectorOfTable: {
@@ -2601,7 +2622,8 @@ class RustGenerator : public BaseGenerator {
}
// Generate an accessor struct with constructor for a flatbuffers struct.
void GenStruct(const StructDef &struct_def) {
const bool is_private = parser_.opts.no_leak_private_annotations &&
const bool is_private =
parser_.opts.no_leak_private_annotations &&
(struct_def.attributes.Lookup("private") != nullptr);
code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
// Generates manual padding and alignment.
@@ -2665,7 +2687,9 @@ class RustGenerator : public BaseGenerator {
code_ += " type Output = {{STRUCT_TY}};";
code_ += " #[inline]";
code_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {";
code_ += " let src = ::core::slice::from_raw_parts(self as *const {{STRUCT_TY}} as *const u8, Self::size());";
code_ +=
" let src = ::core::slice::from_raw_parts(self as *const "
"{{STRUCT_TY}} as *const u8, Self::size());";
code_ += " dst.copy_from_slice(src);";
code_ += " }";
code_ += "}";
@@ -2759,7 +2783,9 @@ class RustGenerator : public BaseGenerator {
code_ += " // Safety:";
code_ += " // Created from a valid Table for this object";
code_ += " // Which contains a valid array in this slot";
code_ += " unsafe { flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}}) }";
code_ +=
" unsafe { flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}}) "
"}";
} else {
code_ += "pub fn {{FIELD}}(&self) -> {{FIELD_TYPE}} {";
code_ +=
@@ -2772,7 +2798,9 @@ class RustGenerator : public BaseGenerator {
code_ += " core::ptr::copy_nonoverlapping(";
code_ += " self.0[{{FIELD_OFFSET}}..].as_ptr(),";
code_ += " mem.as_mut_ptr() as *mut u8,";
code_ += " core::mem::size_of::<<{{FIELD_TYPE}} as EndianScalar>::Scalar>(),";
code_ +=
" core::mem::size_of::<<{{FIELD_TYPE}} as "
"EndianScalar>::Scalar>(),";
code_ += " );";
code_ += " mem.assume_init()";
code_ += " })";
@@ -2827,7 +2855,9 @@ class RustGenerator : public BaseGenerator {
code_ += " core::ptr::copy_nonoverlapping(";
code_ += " &x_le as *const _ as *const u8,";
code_ += " self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),";
code_ += " core::mem::size_of::<<{{FIELD_TYPE}} as EndianScalar>::Scalar>(),";
code_ +=
" core::mem::size_of::<<{{FIELD_TYPE}} as "
"EndianScalar>::Scalar>(),";
code_ += " );";
code_ += " }";
}
@@ -2989,14 +3019,14 @@ class RustGenerator : public BaseGenerator {
} // namespace rust
bool GenerateRust(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateRust(const Parser &parser, const std::string &path,
const std::string &file_name) {
rust::RustGenerator generator(parser, path, file_name);
return generator.generate();
}
std::string RustMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
static std::string RustMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
std::string filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
rust::RustGenerator generator(parser, path, file_name);
@@ -3020,9 +3050,8 @@ class RustCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+26 -23
View File
@@ -148,7 +148,7 @@ static std::string GenArrayMainBody(const std::string &optional) {
optional + " { ";
}
} // namespace
} // namespace
class SwiftGenerator : public BaseGenerator {
private:
@@ -261,8 +261,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += "private var _{{FIELDVAR}}: " + valueType;
const auto accessing_value = IsEnum(field.value.type) ? ".value" : "";
const auto base_value =
IsStruct(field.value.type) ? (type + "()")
: SwiftConstant(field);
IsStruct(field.value.type) ? (type + "()") : SwiftConstant(field);
main_constructor.push_back("_" + field_var + " = " + field_var +
accessing_value);
@@ -720,8 +719,7 @@ class SwiftGenerator : public BaseGenerator {
if (IsBool(field.value.type.base_type)) {
std::string default_value =
field.IsOptional() ? "nil"
: SwiftConstant(field);
field.IsOptional() ? "nil" : SwiftConstant(field);
code_.SetValue("CONSTANT", default_value);
code_.SetValue("VALUETYPE", "Bool");
code_ += GenReaderMainBody(optional) + "\\";
@@ -984,8 +982,9 @@ class SwiftGenerator : public BaseGenerator {
} else if (IsEnum(type) && !field.IsOptional()) {
code_.SetValue("CONSTANT", GenEnumDefaultValue(field));
code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
} else if (IsFloat(type.base_type) && StringIsFlatbufferNan(field.value.constant)) {
code_ += "if !{{FIELDVAR}}.isNaN {";
} else if (IsFloat(type.base_type) &&
StringIsFlatbufferNan(field.value.constant)) {
code_ += "if !{{FIELDVAR}}.isNaN {";
} else if (IsScalar(type.base_type) && !IsEnum(type) &&
!IsBool(type.base_type) && !field.IsOptional()) {
code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
@@ -1158,8 +1157,9 @@ class SwiftGenerator : public BaseGenerator {
void GenEnum(const EnumDef &enum_def) {
if (enum_def.generated) return;
const bool is_private_access = parser_.opts.swift_implementation_only ||
enum_def.attributes.Lookup("private") != nullptr;
const bool is_private_access =
parser_.opts.swift_implementation_only ||
enum_def.attributes.Lookup("private") != nullptr;
code_.SetValue("ENUM_TYPE",
enum_def.is_union ? "UnionEnum" : "Enum, Verifiable");
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
@@ -1579,7 +1579,8 @@ class SwiftGenerator : public BaseGenerator {
if (IsBool(field.value.type.base_type)) {
code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: Bool" + nullable;
if (!field.IsOptional())
base_constructor.push_back(field_var + " = " + SwiftConstant(field));
base_constructor.push_back(field_var + " = " +
SwiftConstant(field));
}
}
}
@@ -1827,22 +1828,24 @@ class SwiftGenerator : public BaseGenerator {
}
}
std::string SwiftConstant(const FieldDef& field) {
std::string SwiftConstant(const FieldDef &field) {
const auto default_value =
StringIsFlatbufferNan(field.value.constant) ? ".nan" :
StringIsFlatbufferPositiveInfinity(field.value.constant) ? ".infinity" :
StringIsFlatbufferNegativeInfinity(field.value.constant) ? "-.infinity" :
IsBool(field.value.type.base_type) ? ("0" == field.value.constant ? "false" : "true") :
field.value.constant;
StringIsFlatbufferNan(field.value.constant) ? ".nan"
: StringIsFlatbufferPositiveInfinity(field.value.constant) ? ".infinity"
: StringIsFlatbufferNegativeInfinity(field.value.constant)
? "-.infinity"
: IsBool(field.value.type.base_type)
? ("0" == field.value.constant ? "false" : "true")
: field.value.constant;
return default_value;
}
}
std::string GenEnumConstructor(const std::string &at) {
return "{{VALUETYPE}}(rawValue: " + GenReader("BASEVALUE", at) + ") ";
}
std::string ValidateFunc() {
return "static func validateVersion() { FlatBuffersVersion_23_3_3() }";
return "static func validateVersion() { FlatBuffersVersion_23_5_26() }";
}
std::string GenType(const Type &type,
@@ -1899,8 +1902,9 @@ class SwiftGenerator : public BaseGenerator {
IdlNamer namer_;
};
} // namespace swift
bool GenerateSwift(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateSwift(const Parser &parser, const std::string &path,
const std::string &file_name) {
swift::SwiftGenerator generator(parser, path, file_name);
return generator.generate();
}
@@ -1915,9 +1919,8 @@ class SwiftCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+121 -91
View File
@@ -19,6 +19,7 @@
#include <algorithm>
#include "flatbuffers/base.h"
#include "flatbuffers/code_generator.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/flexbuffers.h"
@@ -29,8 +30,12 @@ namespace flatbuffers {
struct PrintScalarTag {};
struct PrintPointerTag {};
template<typename T> struct PrintTag { typedef PrintScalarTag type; };
template<> struct PrintTag<const void *> { typedef PrintPointerTag type; };
template<typename T> struct PrintTag {
typedef PrintScalarTag type;
};
template<> struct PrintTag<const void *> {
typedef PrintPointerTag type;
};
struct JsonPrinter {
// If indentation is less than 0, that indicates we don't want any newlines
@@ -54,10 +59,10 @@ struct JsonPrinter {
// for a single FlatBuffer value into JSON format.
// The general case for scalars:
template<typename T>
bool PrintScalar(T val, const Type &type, int /*indent*/) {
void PrintScalar(T val, const Type &type, int /*indent*/) {
if (IsBool(type.base_type)) {
text += val != 0 ? "true" : "false";
return true; // done
return; // done
}
if (opts.output_enum_identifiers && type.enum_def) {
@@ -66,7 +71,7 @@ struct JsonPrinter {
text += '\"';
text += ev->name;
text += '\"';
return true; // done
return; // done
} else if (val && enum_def.attributes.Lookup("bit_flags")) {
const auto entry_len = text.length();
const auto u64 = static_cast<uint64_t>(val);
@@ -84,7 +89,7 @@ struct JsonPrinter {
// Don't slice if (u64 != mask)
if (mask && (u64 == mask)) {
text[text.length() - 1] = '\"';
return true; // done
return; // done
}
text.resize(entry_len); // restore
}
@@ -92,7 +97,7 @@ struct JsonPrinter {
}
text += NumToString(val);
return true;
return;
}
void AddComma() {
@@ -101,36 +106,37 @@ struct JsonPrinter {
// Print a vector or an array of JSON values, comma seperated, wrapped in
// "[]".
template<typename Container>
bool PrintContainer(PrintScalarTag, const Container &c, size_t size,
const Type &type, int indent, const uint8_t *) {
template<typename Container, typename SizeT = typename Container::size_type>
const char *PrintContainer(PrintScalarTag, const Container &c, SizeT size,
const Type &type, int indent, const uint8_t *) {
const auto elem_indent = indent + Indent();
text += '[';
AddNewLine();
for (uoffset_t i = 0; i < size; i++) {
for (SizeT i = 0; i < size; i++) {
if (i) {
AddComma();
AddNewLine();
}
AddIndent(elem_indent);
if (!PrintScalar(c[i], type, elem_indent)) { return false; }
PrintScalar(c[i], type, elem_indent);
}
AddNewLine();
AddIndent(indent);
text += ']';
return true;
return nullptr;
}
// Print a vector or an array of JSON values, comma seperated, wrapped in
// "[]".
template<typename Container>
bool PrintContainer(PrintPointerTag, const Container &c, size_t size,
const Type &type, int indent, const uint8_t *prev_val) {
template<typename Container, typename SizeT = typename Container::size_type>
const char *PrintContainer(PrintPointerTag, const Container &c, SizeT size,
const Type &type, int indent,
const uint8_t *prev_val) {
const auto is_struct = IsStruct(type);
const auto elem_indent = indent + Indent();
text += '[';
AddNewLine();
for (uoffset_t i = 0; i < size; i++) {
for (SizeT i = 0; i < size; i++) {
if (i) {
AddComma();
AddNewLine();
@@ -139,21 +145,20 @@ struct JsonPrinter {
auto ptr = is_struct ? reinterpret_cast<const void *>(
c.Data() + type.struct_def->bytesize * i)
: c[i];
if (!PrintOffset(ptr, type, elem_indent, prev_val,
static_cast<soffset_t>(i))) {
return false;
}
auto err = PrintOffset(ptr, type, elem_indent, prev_val,
static_cast<soffset_t>(i));
if (err) return err;
}
AddNewLine();
AddIndent(indent);
text += ']';
return true;
return nullptr;
}
template<typename T>
bool PrintVector(const void *val, const Type &type, int indent,
const uint8_t *prev_val) {
typedef Vector<T> Container;
template<typename T, typename SizeT = uoffset_t>
const char *PrintVector(const void *val, const Type &type, int indent,
const uint8_t *prev_val) {
typedef Vector<T, SizeT> Container;
typedef typename PrintTag<typename Container::return_type>::type tag;
auto &vec = *reinterpret_cast<const Container *>(val);
return PrintContainer<Container>(tag(), vec, vec.size(), type, indent,
@@ -162,15 +167,17 @@ struct JsonPrinter {
// Print an array a sequence of JSON values, comma separated, wrapped in "[]".
template<typename T>
bool PrintArray(const void *val, size_t size, const Type &type, int indent) {
const char *PrintArray(const void *val, uint16_t size, const Type &type,
int indent) {
typedef Array<T, 0xFFFF> Container;
typedef typename PrintTag<typename Container::return_type>::type tag;
auto &arr = *reinterpret_cast<const Container *>(val);
return PrintContainer<Container>(tag(), arr, size, type, indent, nullptr);
}
bool PrintOffset(const void *val, const Type &type, int indent,
const uint8_t *prev_val, soffset_t vector_index) {
const char *PrintOffset(const void *val, const Type &type, int indent,
const uint8_t *prev_val, soffset_t vector_index) {
switch (type.base_type) {
case BASE_TYPE_UNION: {
// If this assert hits, you have an corrupt buffer, a union type field
@@ -186,7 +193,7 @@ struct JsonPrinter {
if (enum_val) {
return PrintOffset(val, enum_val->union_type, indent, nullptr, -1);
} else {
return false;
return "unknown enum value";
}
}
case BASE_TYPE_STRUCT:
@@ -194,8 +201,9 @@ struct JsonPrinter {
indent);
case BASE_TYPE_STRING: {
auto s = reinterpret_cast<const String *>(val);
return EscapeString(s->c_str(), s->size(), &text, opts.allow_non_utf8,
opts.natural_utf8);
bool ok = EscapeString(s->c_str(), s->size(), &text,
opts.allow_non_utf8, opts.natural_utf8);
return ok ? nullptr : "string contains non-utf8 bytes";
}
case BASE_TYPE_VECTOR: {
const auto vec_type = type.VectorType();
@@ -203,17 +211,15 @@ struct JsonPrinter {
// clang-format off
switch (vec_type.base_type) {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
case BASE_TYPE_ ## ENUM: \
if (!PrintVector<CTYPE>( \
val, vec_type, indent, prev_val)) { \
return false; \
} \
break;
case BASE_TYPE_ ## ENUM: { \
auto err = PrintVector<CTYPE>(val, vec_type, indent, prev_val); \
if (err) return err; \
break; }
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
}
// clang-format on
return true;
return nullptr;
}
case BASE_TYPE_ARRAY: {
const auto vec_type = type.VectorType();
@@ -221,12 +227,10 @@ struct JsonPrinter {
// clang-format off
switch (vec_type.base_type) {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
case BASE_TYPE_ ## ENUM: \
if (!PrintArray<CTYPE>( \
val, type.fixed_length, vec_type, indent)) { \
return false; \
} \
break;
case BASE_TYPE_ ## ENUM: { \
auto err = PrintArray<CTYPE>(val, type.fixed_length, vec_type, indent); \
if (err) return err; \
break; }
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
// Arrays of scalars or structs are only possible.
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
@@ -234,14 +238,14 @@ struct JsonPrinter {
case BASE_TYPE_ARRAY: FLATBUFFERS_ASSERT(0);
}
// clang-format on
return true;
return nullptr;
}
default: FLATBUFFERS_ASSERT(0); return false;
default: FLATBUFFERS_ASSERT(0); return "unknown type";
}
}
template<typename T> static T GetFieldDefault(const FieldDef &fd) {
T val;
T val{};
auto check = StringToNumber(fd.value.constant.c_str(), &val);
(void)check;
FLATBUFFERS_ASSERT(check);
@@ -250,30 +254,28 @@ struct JsonPrinter {
// Generate text for a scalar field.
template<typename T>
bool GenField(const FieldDef &fd, const Table *table, bool fixed,
void GenField(const FieldDef &fd, const Table *table, bool fixed,
int indent) {
if (fixed) {
return PrintScalar(
PrintScalar(
reinterpret_cast<const Struct *>(table)->GetField<T>(fd.value.offset),
fd.value.type, indent);
} else if (fd.IsOptional()) {
auto opt = table->GetOptional<T, T>(fd.value.offset);
if (opt) {
return PrintScalar(*opt, fd.value.type, indent);
PrintScalar(*opt, fd.value.type, indent);
} else {
text += "null";
return true;
}
} else {
return PrintScalar(
table->GetField<T>(fd.value.offset, GetFieldDefault<T>(fd)),
fd.value.type, indent);
PrintScalar(table->GetField<T>(fd.value.offset, GetFieldDefault<T>(fd)),
fd.value.type, indent);
}
}
// Generate text for non-scalar field.
bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
int indent, const uint8_t *prev_val) {
const char *GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
int indent, const uint8_t *prev_val) {
const void *val = nullptr;
if (fixed) {
// The only non-scalar fields in structs are structs or arrays.
@@ -290,7 +292,7 @@ struct JsonPrinter {
auto vec = table->GetPointer<const Vector<uint8_t> *>(fd.value.offset);
auto root = flexbuffers::GetRoot(vec->data(), vec->size());
root.ToString(true, opts.strict_json, text);
return true;
return nullptr;
} else if (fd.nested_flatbuffer && opts.json_nested_flatbuffers) {
auto vec = table->GetPointer<const Vector<uint8_t> *>(fd.value.offset);
auto root = GetRoot<Table>(vec->data());
@@ -305,7 +307,8 @@ struct JsonPrinter {
// Generate text for a struct or table, values separated by commas, indented,
// and bracketed by "{}"
bool GenStruct(const StructDef &struct_def, const Table *table, int indent) {
const char *GenStruct(const StructDef &struct_def, const Table *table,
int indent) {
text += '{';
int fieldout = 0;
const uint8_t *prev_val = nullptr;
@@ -329,11 +332,9 @@ struct JsonPrinter {
// clang-format off
switch (fd.value.type.base_type) {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
case BASE_TYPE_ ## ENUM: \
if (!GenField<CTYPE>(fd, table, struct_def.fixed, elem_indent)) { \
return false; \
} \
break;
case BASE_TYPE_ ## ENUM: { \
GenField<CTYPE>(fd, table, struct_def.fixed, elem_indent); \
break; }
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
// Generate drop-thru case statements for all pointer types:
@@ -342,10 +343,11 @@ struct JsonPrinter {
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
FLATBUFFERS_GEN_TYPE_ARRAY(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
if (!GenFieldOffset(fd, table, struct_def.fixed, elem_indent, prev_val)) {
return false;
}
break;
{
auto err = GenFieldOffset(fd, table, struct_def.fixed, elem_indent, prev_val);
if (err) return err;
break;
}
}
// clang-format on
// Track prev val for use with union types.
@@ -359,7 +361,7 @@ struct JsonPrinter {
AddNewLine();
AddIndent(indent);
text += '}';
return true;
return nullptr;
}
JsonPrinter(const Parser &parser, std::string &dest)
@@ -371,26 +373,42 @@ struct JsonPrinter {
std::string &text;
};
static bool GenerateTextImpl(const Parser &parser, const Table *table,
const StructDef &struct_def, std::string *_text) {
static const char *GenerateTextImpl(const Parser &parser, const Table *table,
const StructDef &struct_def,
std::string *_text) {
JsonPrinter printer(parser, *_text);
if (!printer.GenStruct(struct_def, table, 0)) { return false; }
auto err = printer.GenStruct(struct_def, table, 0);
if (err) return err;
printer.AddNewLine();
return true;
return nullptr;
}
// Generate a text representation of a flatbuffer in JSON format.
// Deprecated: please use `GenTextFromTable`
bool GenerateTextFromTable(const Parser &parser, const void *table,
const std::string &table_name, std::string *_text) {
const std::string &table_name,
std::string *_text) {
return GenTextFromTable(parser, table, table_name, _text) != nullptr;
}
// Generate a text representation of a flatbuffer in JSON format.
const char *GenTextFromTable(const Parser &parser, const void *table,
const std::string &table_name, std::string *_text) {
auto struct_def = parser.LookupStruct(table_name);
if (struct_def == nullptr) { return false; }
if (struct_def == nullptr) { return "unknown struct"; }
auto root = static_cast<const Table *>(table);
return GenerateTextImpl(parser, root, *struct_def, _text);
}
// Deprecated: please use `GenText`
const char *GenerateText(const Parser &parser, const void *flatbuffer,
std::string *_text) {
return GenText(parser, flatbuffer, _text);
}
// Generate a text representation of a flatbuffer in JSON format.
bool GenerateText(const Parser &parser, const void *flatbuffer,
std::string *_text) {
const char *GenText(const Parser &parser, const void *flatbuffer,
std::string *_text) {
FLATBUFFERS_ASSERT(parser.root_struct_def_); // call SetRootType()
auto root = parser.opts.size_prefixed ? GetSizePrefixedRoot<Table>(flatbuffer)
: GetRoot<Table>(flatbuffer);
@@ -402,25 +420,34 @@ static std::string TextFileName(const std::string &path,
return path + file_name + ".json";
}
bool GenerateTextFile(const Parser &parser, const std::string &path,
const std::string &file_name) {
// Deprecated: please use `GenTextFile`
const char *GenerateTextFile(const Parser &parser, const std::string &path,
const std::string &file_name) {
return GenTextFile(parser, path, file_name);
}
const char *GenTextFile(const Parser &parser, const std::string &path,
const std::string &file_name) {
if (parser.opts.use_flexbuffers) {
std::string json;
parser.flex_root_.ToString(true, parser.opts.strict_json, json);
return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(),
json.c_str(), json.size(), true);
json.c_str(), json.size(), true)
? nullptr
: "SaveFile failed";
}
if (!parser.builder_.GetSize() || !parser.root_struct_def_) return true;
if (!parser.builder_.GetSize() || !parser.root_struct_def_) return nullptr;
std::string text;
if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &text)) {
return false;
}
auto err = GenText(parser, parser.builder_.GetBufferPointer(), &text);
if (err) return err;
return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(), text,
false);
false)
? nullptr
: "SaveFile failed";
}
std::string TextMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
static std::string TextMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
if (!parser.builder_.GetSize() || !parser.root_struct_def_) return "";
std::string filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
@@ -439,15 +466,18 @@ class TextCodeGenerator : public CodeGenerator {
public:
Status GenerateCode(const Parser &parser, const std::string &path,
const std::string &filename) override {
if (!GenerateTextFile(parser, path, filename)) { return Status::ERROR; }
auto err = GenTextFile(parser, path, filename);
if (err) {
status_detail = " (" + std::string(err) + ")";
return Status::ERROR;
}
return Status::OK;
}
// Generate code from the provided `buffer` of given `length`. The buffer is a
// serialized reflection.fbs.
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+33 -18
View File
@@ -408,7 +408,7 @@ class TsGenerator : public BaseGenerator {
switch (type.base_type) {
case BASE_TYPE_BOOL:
case BASE_TYPE_CHAR: return "Int8";
case BASE_TYPE_UTYPE:
case BASE_TYPE_UTYPE: return GenType(GetUnionUnderlyingType(type));
case BASE_TYPE_UCHAR: return "Uint8";
case BASE_TYPE_SHORT: return "Int16";
case BASE_TYPE_USHORT: return "Uint16";
@@ -477,10 +477,9 @@ class TsGenerator : public BaseGenerator {
EnumVal *val = value.type.enum_def->FindByValue(value.constant);
if (val == nullptr)
val = const_cast<EnumVal *>(value.type.enum_def->MinValue());
return AddImport(imports, *value.type.enum_def,
*value.type.enum_def)
.name +
"." + namer_.Variant(*val);
return AddImport(imports, *value.type.enum_def, *value.type.enum_def)
.name +
"." + namer_.Variant(*val);
}
}
}
@@ -563,11 +562,26 @@ class TsGenerator : public BaseGenerator {
}
}
static Type GetUnionUnderlyingType(const Type &type)
{
if (type.enum_def != nullptr &&
type.enum_def->underlying_type.base_type != type.base_type) {
return type.enum_def->underlying_type;
} else {
return Type(BASE_TYPE_UCHAR);
}
}
static Type GetUnderlyingVectorType(const Type &vector_type)
{
return (vector_type.base_type == BASE_TYPE_UTYPE) ? GetUnionUnderlyingType(vector_type) : vector_type;
}
// Returns the method name for use with add/put calls.
std::string GenWriteMethod(const Type &type) {
// Forward to signed versions since unsigned versions don't exist
switch (type.base_type) {
case BASE_TYPE_UTYPE:
case BASE_TYPE_UTYPE: return GenWriteMethod(GetUnionUnderlyingType(type));
case BASE_TYPE_UCHAR: return GenWriteMethod(Type(BASE_TYPE_CHAR));
case BASE_TYPE_USHORT: return GenWriteMethod(Type(BASE_TYPE_SHORT));
case BASE_TYPE_UINT: return GenWriteMethod(Type(BASE_TYPE_INT));
@@ -850,8 +864,8 @@ class TsGenerator : public BaseGenerator {
}
if (enum_def.is_union) {
symbols_expression += ", unionTo" + name;
symbols_expression += ", unionListTo" + name;
symbols_expression += (", " + namer_.Function("unionTo" + name));
symbols_expression += (", " + namer_.Function("unionListTo" + name));
}
return symbols_expression;
@@ -1764,7 +1778,8 @@ class TsGenerator : public BaseGenerator {
auto vectortype = field.value.type.VectorType();
auto vectortypename =
GenTypeName(imports, struct_def, vectortype, false);
auto inline_size = InlineSize(vectortype);
auto type = GetUnderlyingVectorType(vectortype);
auto inline_size = InlineSize(type);
auto index = GenBBAccess() +
".__vector(this.bb_pos + offset) + index" +
MaybeScale(inline_size);
@@ -1991,8 +2006,9 @@ class TsGenerator : public BaseGenerator {
if (IsVector(field.value.type)) {
auto vector_type = field.value.type.VectorType();
auto alignment = InlineAlignment(vector_type);
auto elem_size = InlineSize(vector_type);
auto type = GetUnderlyingVectorType(vector_type);
auto alignment = InlineAlignment(type);
auto elem_size = InlineSize(type);
// Generate a method to create a vector from a JavaScript array
if (!IsStruct(vector_type)) {
@@ -2157,14 +2173,14 @@ class TsGenerator : public BaseGenerator {
}; // namespace ts
} // namespace ts
bool GenerateTS(const Parser &parser, const std::string &path,
const std::string &file_name) {
static bool GenerateTS(const Parser &parser, const std::string &path,
const std::string &file_name) {
ts::TsGenerator generator(parser, path, file_name);
return generator.generate();
}
std::string TSMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
static std::string TSMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
std::string filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
ts::TsGenerator generator(parser, path, file_name);
@@ -2188,9 +2204,8 @@ class TsCodeGenerator : public CodeGenerator {
return Status::OK;
}
Status GenerateCode(const uint8_t *buffer, int64_t length) override {
(void)buffer;
(void)length;
Status GenerateCode(const uint8_t *, int64_t,
const CodeGenOptions &) override {
return Status::NOT_IMPLEMENTED;
}
+5 -3
View File
@@ -88,8 +88,9 @@ class IdlNamer : public Namer {
}
std::string Directories(const struct Namespace &ns,
SkipDir skips = SkipDir::None) const {
return Directories(ns.components, skips);
SkipDir skips = SkipDir::None,
Case input_case = Case::kUpperCamel) const {
return Directories(ns.components, skips, input_case);
}
// Legacy fields do not really follow the usual config and should be
@@ -146,7 +147,8 @@ class IdlNamer : public Namer {
std::string LegacyRustUnionTypeMethod(const FieldDef &d) {
// assert d is a union
return Method(d.name + "_type");
// d should convert case but not escape keywords due to historical reasons
return ConvertCase(d.name, config_.fields, Case::kLowerCamel) + "_type";
}
private:
+194 -56
View File
@@ -16,12 +16,15 @@
#include <algorithm>
#include <cmath>
#include <iostream>
#include <list>
#include <string>
#include <utility>
#include "flatbuffers/base.h"
#include "flatbuffers/buffer.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/reflection_generated.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
@@ -42,7 +45,8 @@ static const double kPi = 3.14159265358979323846;
// The enums in the reflection schema should match the ones we use internally.
// Compare the last element to check if these go out of sync.
static_assert(BASE_TYPE_UNION == static_cast<BaseType>(reflection::Union),
static_assert(BASE_TYPE_VECTOR64 ==
static_cast<BaseType>(reflection::MaxBaseType - 1),
"enums don't match");
// Any parsing calls have to be wrapped in this macro, which automates
@@ -124,6 +128,14 @@ CheckedError atot<Offset<void>>(const char *s, Parser &parser,
return NoError();
}
template<>
CheckedError atot<Offset64<void>>(const char *s, Parser &parser,
Offset64<void> *val) {
(void)parser;
*val = Offset64<void>(atoi(s));
return NoError();
}
template<typename T>
static T *LookupTableByName(const SymbolTable<T> &table,
const std::string &name,
@@ -935,8 +947,12 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (type.base_type == BASE_TYPE_UNION) {
// For union fields, add a second auto-generated field to hold the type,
// with a special suffix.
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
type.enum_def->underlying_type, &typefield));
// To ensure compatibility with many codes that rely on the BASE_TYPE_UTYPE value to identify union type fields.
Type union_type(type.enum_def->underlying_type);
union_type.base_type = BASE_TYPE_UTYPE;
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),union_type, &typefield));
} else if (IsVector(type) && type.element == BASE_TYPE_UNION) {
advanced_features_ |= reflection::AdvancedUnionFeatures;
// Only cpp, js and ts supports the union vector feature so far.
@@ -957,11 +973,11 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
ECHECK(AddField(struct_def, name, type, &field));
if (typefield) {
// We preserve the relation between the typefield
// and field, so we can easily map it in the code
// generators.
typefield->sibling_union_field = field;
field->sibling_union_field = typefield;
// We preserve the relation between the typefield
// and field, so we can easily map it in the code
// generators.
typefield->sibling_union_field = field;
field->sibling_union_field = typefield;
}
if (token_ == '=') {
@@ -1036,6 +1052,65 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
}
}
if (field->attributes.Lookup("vector64") != nullptr) {
if (!IsVector(type)) {
return Error("`vector64` attribute can only be applied on vectors.");
}
// Upgrade the type to be a BASE_TYPE_VECTOR64, since the attributes are
// parsed after the type.
const BaseType element_base_type = type.element;
type = Type(BASE_TYPE_VECTOR64, type.struct_def, type.enum_def);
type.element = element_base_type;
// Since the field was already added to the parent object, update the type
// in place.
field->value.type = type;
// 64-bit vectors imply the offset64 attribute.
field->offset64 = true;
}
// Record that this field uses 64-bit offsets.
if (field->attributes.Lookup("offset64") != nullptr) {
// TODO(derekbailey): would be nice to have this be a recommendation or hint
// instead of a warning.
if (type.base_type == BASE_TYPE_VECTOR64) {
Warning("attribute `vector64` implies `offset64` and isn't required.");
}
field->offset64 = true;
}
// Check for common conditions with Offset64 fields.
if (field->offset64) {
// TODO(derekbailey): this is where we can disable string support for
// offset64, as that is not a hard requirement to have.
if (!IsString(type) && !IsVector(type)) {
return Error(
"only string and vectors can have `offset64` attribute applied");
}
// If this is a Vector, only scalar and scalar-like (structs) items are
// allowed.
// TODO(derekbailey): allow vector of strings, just require that the strings
// are Offset64<string>.
if (IsVector(type) &&
!((IsScalar(type.element) && !IsEnum(type.VectorType())) ||
IsStruct(type.VectorType()))) {
return Error("only vectors of scalars are allowed to be 64-bit.");
}
// Lastly, check if it is supported by the specified generated languages. Do
// this last so the above checks can inform the user of schema errors to fix
// first.
if (!Supports64BitOffsets()) {
return Error(
"fields using 64-bit offsets are not yet supported in at least one "
"of the specified programming languages.");
}
}
// For historical convenience reasons, string keys are assumed required.
// Scalars are kDefault unless otherwise specified.
// Nonscalars are kOptional unless required;
@@ -1058,7 +1133,8 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (field->key) {
if (struct_def.has_key) return Error("only one field may be set as 'key'");
struct_def.has_key = true;
auto is_valid = IsScalar(type.base_type) || IsString(type) || IsStruct(type);
auto is_valid =
IsScalar(type.base_type) || IsString(type) || IsStruct(type);
if (IsArray(type)) {
is_valid |=
IsScalar(type.VectorType().base_type) || IsStruct(type.VectorType());
@@ -1161,7 +1237,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (nested->type.base_type != BASE_TYPE_STRING)
return Error(
"nested_flatbuffer attribute must be a string (the root type)");
if (type.base_type != BASE_TYPE_VECTOR || type.element != BASE_TYPE_UCHAR)
if (!IsVector(type.base_type) || type.element != BASE_TYPE_UCHAR)
return Error(
"nested_flatbuffer attribute may only apply to a vector of ubyte");
// This will cause an error if the root type of the nested flatbuffer
@@ -1230,7 +1306,7 @@ CheckedError Parser::ParseComma() {
CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn,
const StructDef *parent_struct_def,
uoffset_t count, bool inside_vector) {
size_t count, bool inside_vector) {
switch (val.type.base_type) {
case BASE_TYPE_UNION: {
FLATBUFFERS_ASSERT(field);
@@ -1300,7 +1376,7 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
return Error(
"union types vector smaller than union values vector for: " +
field->name);
enum_idx = vector_of_union_types->Get(count);
enum_idx = vector_of_union_types->Get(static_cast<uoffset_t>(count));
} else {
ECHECK(atot(constant.c_str(), *this, &enum_idx));
}
@@ -1329,9 +1405,10 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
ECHECK(ParseString(val, field->shared));
break;
}
case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
uoffset_t off;
ECHECK(ParseVector(val.type.VectorType(), &off, field, parent_fieldn));
ECHECK(ParseVector(val.type, &off, field, parent_fieldn));
val.constant = NumToString(off);
break;
}
@@ -1503,6 +1580,9 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; size;
size /= 2) {
// Go through elements in reverse, since we're building the data backwards.
// TODO(derekbailey): this doesn't work when there are Offset64 fields, as
// those have to be built first. So this needs to be changed to iterate over
// Offset64 then Offset32 fields.
for (auto it = field_stack_.rbegin();
it != field_stack_.rbegin() + fieldn_outer; ++it) {
auto &field_value = it->first;
@@ -1510,7 +1590,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
if (!struct_def.sortbysize ||
size == SizeOf(field_value.type.base_type)) {
switch (field_value.type.base_type) {
// clang-format off
// clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
case BASE_TYPE_ ## ENUM: \
builder_.Pad(field->padding); \
@@ -1541,9 +1621,16 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
if (IsStruct(field->value.type)) { \
SerializeStruct(*field->value.type.struct_def, field_value); \
} else { \
CTYPE val; \
ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
builder_.AddOffset(field_value.offset, val); \
/* Special case for fields that use 64-bit addressing */ \
if(field->offset64) { \
Offset64<void> offset; \
ECHECK(atot(field_value.constant.c_str(), *this, &offset)); \
builder_.AddOffset(field_value.offset, offset); \
} else { \
CTYPE val; \
ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
builder_.AddOffset(field_value.offset, val); \
} \
} \
break;
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
@@ -1581,7 +1668,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
}
template<typename F>
CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) {
CheckedError Parser::ParseVectorDelimiters(size_t &count, F body) {
EXPECT('[');
for (;;) {
if ((!opts.strict_json || !count) && Is(']')) break;
@@ -1611,10 +1698,11 @@ CheckedError Parser::ParseAlignAttribute(const std::string &align_constant,
NumToString(FLATBUFFERS_MAX_ALIGNMENT));
}
CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
CheckedError Parser::ParseVector(const Type &vector_type, uoffset_t *ovalue,
FieldDef *field, size_t fieldn) {
uoffset_t count = 0;
auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
Type type = vector_type.VectorType();
size_t count = 0;
auto err = ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
Value val;
val.type = type;
ECHECK(ParseAnyValue(val, field, fieldn, nullptr, count, true));
@@ -1634,12 +1722,18 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
}
// TODO Fix using element alignment as size (`elemsize`)!
builder_.StartVector(len, elemsize, alignment);
for (uoffset_t i = 0; i < count; i++) {
if (vector_type.base_type == BASE_TYPE_VECTOR64) {
// TODO(derekbailey): this requires a 64-bit builder.
// builder_.StartVector<Offset64, uoffset64_t>(len, elemsize, alignment);
builder_.StartVector(len, elemsize, alignment);
} else {
builder_.StartVector(len, elemsize, alignment);
}
for (size_t i = 0; i < count; i++) {
// start at the back, since we're building the data backwards.
auto &val = field_stack_.back().first;
switch (val.type.base_type) {
// clang-format off
// clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE,...) \
case BASE_TYPE_ ## ENUM: \
if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \
@@ -1657,7 +1751,11 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
}
builder_.ClearOffsets();
*ovalue = builder_.EndVector(count);
if (vector_type.base_type == BASE_TYPE_VECTOR64) {
*ovalue = builder_.EndVector<uoffset64_t>(count);
} else {
*ovalue = builder_.EndVector(count);
}
if (type.base_type == BASE_TYPE_STRUCT && type.struct_def->has_key) {
// We should sort this vector. Find the key first.
@@ -1725,8 +1823,8 @@ CheckedError Parser::ParseArray(Value &array) {
FlatBufferBuilder builder;
const auto &type = array.type.VectorType();
auto length = array.type.fixed_length;
uoffset_t count = 0;
auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
size_t count = 0;
auto err = ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
stack.emplace_back(Value());
auto &val = stack.back();
val.type = type;
@@ -1977,8 +2075,7 @@ CheckedError Parser::TryTypedValue(const std::string *name, int dtoken,
e.type.base_type = req;
} else {
return Error(std::string("type mismatch: expecting: ") +
TypeName(e.type.base_type) +
", found: " + TypeName(req) +
TypeName(e.type.base_type) + ", found: " + TypeName(req) +
", name: " + (name ? *name : "") + ", value: " + e.constant);
}
}
@@ -2275,8 +2372,12 @@ template<typename T> void EnumDef::ChangeEnumValue(EnumVal *ev, T new_value) {
}
namespace EnumHelper {
template<BaseType E> struct EnumValType { typedef int64_t type; };
template<> struct EnumValType<BASE_TYPE_ULONG> { typedef uint64_t type; };
template<BaseType E> struct EnumValType {
typedef int64_t type;
};
template<> struct EnumValType<BASE_TYPE_ULONG> {
typedef uint64_t type;
};
} // namespace EnumHelper
struct EnumValBuilder {
@@ -2385,23 +2486,39 @@ CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest,
&GetPooledString(RelativeToRootPath(opts.project_root, filename));
}
enum_def->doc_comment = enum_comment;
if (!is_union && !opts.proto_mode) {
if (!opts.proto_mode) {
// Give specialized error message, since this type spec used to
// be optional in the first FlatBuffers release.
bool explicit_underlying_type = false;
if (!Is(':')) {
return Error(
"must specify the underlying integer type for this"
" enum (e.g. \': short\', which was the default).");
// Enum is forced to have an explicit underlying type in declaration.
if (!is_union) {
return Error(
"must specify the underlying integer type for this"
" enum (e.g. \': short\', which was the default).");
}
} else {
// Union underlying type is only supported for cpp
if (is_union && !SupportsUnionUnderlyingType()) {
return Error(
"Underlying type for union is not yet supported in at least one of "
"the specified programming languages.");
}
NEXT();
explicit_underlying_type = true;
}
// Specify the integer type underlying this enum.
ECHECK(ParseType(enum_def->underlying_type));
if (!IsInteger(enum_def->underlying_type.base_type) ||
IsBool(enum_def->underlying_type.base_type))
return Error("underlying enum type must be integral");
// Make this type refer back to the enum it was derived from.
enum_def->underlying_type.enum_def = enum_def;
if (explicit_underlying_type) {
// Specify the integer type underlying this enum.
ECHECK(ParseType(enum_def->underlying_type));
if (!IsInteger(enum_def->underlying_type.base_type) || IsBool(enum_def->underlying_type.base_type)) {
return Error("underlying " + std::string(is_union ? "union" : "enum") + "type must be integral");
}
// Make this type refer back to the enum it was derived from.
enum_def->underlying_type.enum_def = enum_def;
}
}
ECHECK(ParseMetaData(&enum_def->attributes));
const auto underlying_type = enum_def->underlying_type.base_type;
@@ -2562,9 +2679,10 @@ std::vector<IncludedFile> Parser::GetIncludedFiles() const {
bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts) {
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava |
IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kBinary |
IDLOptions::kGo | IDLOptions::kPython | IDLOptions::kJson |
IDLOptions::kKotlin | IDLOptions::kKotlinKmp | IDLOptions::kCpp |
IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kTs |
IDLOptions::kBinary | IDLOptions::kGo | IDLOptions::kPython |
IDLOptions::kJson |
IDLOptions::kNim;
unsigned long langs = opts.lang_to_generate;
return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
@@ -2585,7 +2703,7 @@ bool Parser::SupportsAdvancedUnionFeatures() const {
~(IDLOptions::kCpp | IDLOptions::kTs | IDLOptions::kPhp |
IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kKotlin |
IDLOptions::kBinary | IDLOptions::kSwift | IDLOptions::kNim |
IDLOptions::kJson)) == 0;
IDLOptions::kJson | IDLOptions::kKotlinKmp)) == 0;
}
bool Parser::SupportsAdvancedArrayFeatures() const {
@@ -2595,6 +2713,16 @@ bool Parser::SupportsAdvancedArrayFeatures() const {
IDLOptions::kBinary | IDLOptions::kRust | IDLOptions::kTs)) == 0;
}
bool Parser::Supports64BitOffsets() const {
return (opts.lang_to_generate &
~(IDLOptions::kCpp | IDLOptions::kJson | IDLOptions::kBinary)) == 0;
}
bool Parser::SupportsUnionUnderlyingType() const {
return (opts.lang_to_generate & ~(IDLOptions::kCpp | IDLOptions::kTs |
IDLOptions::kBinary)) == 0;
}
Namespace *Parser::UniqueNamespace(Namespace *ns) {
for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
if (ns->components == (*it)->components) {
@@ -3217,10 +3345,9 @@ CheckedError Parser::SkipAnyJsonValue() {
});
}
case '[': {
uoffset_t count = 0;
return ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
return SkipAnyJsonValue();
});
size_t count = 0;
return ParseVectorDelimiters(
count, [&](size_t &) -> CheckedError { return SkipAnyJsonValue(); });
}
case kTokenStringConstant:
case kTokenIntegerConstant:
@@ -3269,8 +3396,8 @@ CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) {
}
case '[': {
auto start = builder->StartVector();
uoffset_t count = 0;
ECHECK(ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
size_t count = 0;
ECHECK(ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
return ParseFlexBufferValue(builder);
}));
builder->EndVector(start, false, false);
@@ -3922,7 +4049,7 @@ Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0,
// result may be platform-dependent if underlying is float (not double)
IsFloat(value.type.base_type) ? d : 0.0, deprecated, IsRequired(), key,
attr__, docs__, IsOptional(), static_cast<uint16_t>(padding));
attr__, docs__, IsOptional(), static_cast<uint16_t>(padding), offset64);
// TODO: value.constant is almost always "0", we could save quite a bit of
// space by sharing it. Same for common values of value.type.
}
@@ -3940,6 +4067,7 @@ bool FieldDef::Deserialize(Parser &parser, const reflection::Field *field) {
presence = FieldDef::MakeFieldPresence(field->optional(), field->required());
padding = field->padding();
key = field->key();
offset64 = field->offset64();
if (!DeserializeAttributes(parser, field->attributes())) return false;
// TODO: this should probably be handled by a separate attribute
if (attributes.Lookup("flexbuffer")) {
@@ -4264,12 +4392,18 @@ std::string Parser::ConformTo(const Parser &base) {
auto field_base = struct_def_base->fields.Lookup(field.name);
const auto qualified_field_name = qualified_name + "." + field.name;
if (field_base) {
if (field.value.offset != field_base->value.offset)
if (field.value.offset != field_base->value.offset) {
return "offsets differ for field: " + qualified_field_name;
if (field.value.constant != field_base->value.constant)
}
if (field.value.constant != field_base->value.constant) {
return "defaults differ for field: " + qualified_field_name;
if (!EqualByName(field.value.type, field_base->value.type))
}
if (!EqualByName(field.value.type, field_base->value.type)) {
return "types differ for field: " + qualified_field_name;
}
if (field.offset64 != field_base->offset64) {
return "offset types differ for field: " + qualified_field_name;
}
} else {
// Doesn't have to exist, deleting fields is fine.
// But we should check if there is a field that has the same offset
@@ -4320,6 +4454,10 @@ std::string Parser::ConformTo(const Parser &base) {
return "values differ for enum: " + enum_val.name;
}
}
// Check underlying type changes
if (enum_def_base->underlying_type.base_type != enum_def.underlying_type.base_type) {
return "underlying type differ for " + std::string(enum_def.is_union ? "union: " : "enum: ") + qualified_name;
}
}
return "";
}
+6 -2
View File
@@ -185,15 +185,19 @@ class Namer {
// right seperator. Output path prefixing and the trailing separator may be
// skiped using `skips`.
// Callers may want to use `EnsureDirExists` with the result.
// input_case is used to tell how to modify namespace. e.g. kUpperCamel will
// add a underscode between case changes, so MyGame turns into My_Game
// (depending also on the output_case).
virtual std::string Directories(const std::vector<std::string> &directories,
SkipDir skips = SkipDir::None) const {
SkipDir skips = SkipDir::None,
Case input_case = Case::kUpperCamel) const {
const bool skip_output_path =
(skips & SkipDir::OutputPath) != SkipDir::None;
const bool skip_trailing_seperator =
(skips & SkipDir::TrailingPathSeperator) != SkipDir::None;
std::string result = skip_output_path ? "" : config_.output_path;
for (auto d = directories.begin(); d != directories.end(); d++) {
result += ConvertCase(*d, config_.directories, Case::kUpperCamel);
result += ConvertCase(*d, config_.directories, input_case);
result.push_back(kPathSeparator);
}
if (skip_trailing_seperator && !result.empty()) result.pop_back();
+33 -30
View File
@@ -24,17 +24,18 @@ namespace flatbuffers {
namespace {
static void CopyInline(FlatBufferBuilder &fbb, const reflection::Field &fielddef,
const Table &table, size_t align, size_t size) {
static void CopyInline(FlatBufferBuilder &fbb,
const reflection::Field &fielddef, const Table &table,
size_t align, size_t size) {
fbb.Align(align);
fbb.PushBytes(table.GetStruct<const uint8_t *>(fielddef.offset()), size);
fbb.TrackField(fielddef.offset(), fbb.GetSize());
}
static bool VerifyStruct(flatbuffers::Verifier &v,
const flatbuffers::Table &parent_table,
voffset_t field_offset, const reflection::Object &obj,
bool required) {
const flatbuffers::Table &parent_table,
voffset_t field_offset, const reflection::Object &obj,
bool required) {
auto offset = parent_table.GetOptionalFieldOffset(field_offset);
if (required && !offset) { return false; }
@@ -44,9 +45,10 @@ static bool VerifyStruct(flatbuffers::Verifier &v,
}
static bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
const flatbuffers::Table &parent_table,
voffset_t field_offset,
const reflection::Object &obj, bool required) {
const flatbuffers::Table &parent_table,
voffset_t field_offset,
const reflection::Object &obj,
bool required) {
auto p = parent_table.GetPointer<const uint8_t *>(field_offset);
if (required && !p) { return false; }
@@ -54,13 +56,15 @@ static bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
}
// forward declare to resolve cyclic deps between VerifyObject and VerifyVector
static bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
const reflection::Object &obj,
const flatbuffers::Table *table, bool required);
static bool VerifyObject(flatbuffers::Verifier &v,
const reflection::Schema &schema,
const reflection::Object &obj,
const flatbuffers::Table *table, bool required);
static bool VerifyUnion(flatbuffers::Verifier &v, const reflection::Schema &schema,
uint8_t utype, const uint8_t *elem,
const reflection::Field &union_field) {
static bool VerifyUnion(flatbuffers::Verifier &v,
const reflection::Schema &schema, uint8_t utype,
const uint8_t *elem,
const reflection::Field &union_field) {
if (!utype) return true; // Not present.
auto fb_enum = schema.enums()->Get(union_field.type()->index());
if (utype >= fb_enum->values()->size()) return false;
@@ -83,9 +87,10 @@ static bool VerifyUnion(flatbuffers::Verifier &v, const reflection::Schema &sche
}
}
static bool VerifyVector(flatbuffers::Verifier &v, const reflection::Schema &schema,
const flatbuffers::Table &table,
const reflection::Field &vec_field) {
static bool VerifyVector(flatbuffers::Verifier &v,
const reflection::Schema &schema,
const flatbuffers::Table &table,
const reflection::Field &vec_field) {
FLATBUFFERS_ASSERT(vec_field.type()->base_type() == reflection::Vector);
if (!table.VerifyField<uoffset_t>(v, vec_field.offset(), sizeof(uoffset_t)))
return false;
@@ -161,9 +166,10 @@ static bool VerifyVector(flatbuffers::Verifier &v, const reflection::Schema &sch
}
}
static bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
const reflection::Object &obj,
const flatbuffers::Table *table, bool required) {
static bool VerifyObject(flatbuffers::Verifier &v,
const reflection::Schema &schema,
const reflection::Object &obj,
const flatbuffers::Table *table, bool required) {
if (!table) return !required;
if (!table->VerifyTableStart(v)) return false;
for (uoffset_t i = 0; i < obj.fields()->size(); i++) {
@@ -251,8 +257,7 @@ static bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &sch
return true;
}
} // namespace
} // namespace
int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data) {
// clang-format off
@@ -506,7 +511,9 @@ class ResizeContext {
// Recurse.
switch (base_type) {
case reflection::Obj: {
ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref));
if (subobjectdef) {
ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref));
}
break;
}
case reflection::Vector: {
@@ -564,7 +571,7 @@ void SetString(const reflection::Schema &schema, const std::string &val,
// Clear the old string, since we don't want parts of it remaining.
memset(flatbuf->data() + start, 0, str->size());
// Different size, we must expand (or contract).
ResizeContext(schema, start, delta, flatbuf, root_table);
ResizeContext ctx(schema, start, delta, flatbuf, root_table);
// Set the new length.
WriteScalar(flatbuf->data() + str_start,
static_cast<uoffset_t>(val.size()));
@@ -590,7 +597,7 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
auto size_clear = -delta_elem * elem_size;
memset(flatbuf->data() + start - size_clear, 0, size_clear);
}
ResizeContext(schema, start, delta_bytes, flatbuf, root_table);
ResizeContext ctx(schema, start, delta_bytes, flatbuf, root_table);
WriteScalar(flatbuf->data() + vec_start, newsize); // Length field.
// Set new elements to 0.. this can be overwritten by the caller.
if (delta_elem > 0) {
@@ -616,9 +623,6 @@ const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
return flatbuf.data() + insertion_point + root_offset;
}
Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const reflection::Schema &schema,
const reflection::Object &objectdef,
@@ -689,7 +693,7 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
FLATBUFFERS_FALLTHROUGH(); // fall thru
default: { // Scalars and structs.
auto element_size = GetTypeSize(element_base_type);
auto element_alignment = element_size; // For primitive elements
auto element_alignment = element_size; // For primitive elements
if (elemobjectdef && elemobjectdef->is_struct())
element_size = elemobjectdef->bytesize();
fbb.StartVector(vec->size(), element_size, element_alignment);
@@ -744,7 +748,6 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
}
}
bool Verify(const reflection::Schema &schema, const reflection::Object &root,
const uint8_t *const buf, const size_t length,
const uoffset_t max_depth, const uoffset_t max_tables) {
+16 -13
View File
@@ -90,13 +90,12 @@ static std::string ToCamelCase(const std::string &input, bool is_upper) {
std::string s;
for (size_t i = 0; i < input.length(); i++) {
if (!i && input[i] == '_') {
s += input[i];
// we ignore leading underscore but make following
// alphabet char upper.
if (i + 1 < input.length() && is_alpha(input[i + 1]))
s += CharToUpper(input[++i]);
}
else if (!i)
s += input[i];
// we ignore leading underscore but make following
// alphabet char upper.
if (i + 1 < input.length() && is_alpha(input[i + 1]))
s += CharToUpper(input[++i]);
} else if (!i)
s += is_upper ? CharToUpper(input[i]) : CharToLower(input[i]);
else if (input[i] == '_' && i + 1 < input.length())
s += CharToUpper(input[++i]);
@@ -116,7 +115,10 @@ static std::string ToSnakeCase(const std::string &input, bool screaming) {
} else if (!islower(input[i])) {
// Prevent duplicate underscores for Upper_Snake_Case strings
// and UPPERCASE strings.
if (islower(input[i - 1]) || (isdigit(input[i-1]) && !isdigit(input[i]))) { s += '_'; }
if (islower(input[i - 1]) ||
(isdigit(input[i - 1]) && !isdigit(input[i]))) {
s += '_';
}
s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
} else {
s += screaming ? CharToUpper(input[i]) : input[i];
@@ -126,7 +128,7 @@ static std::string ToSnakeCase(const std::string &input, bool screaming) {
}
std::string ToAll(const std::string &input,
std::function<char(const char)> transform) {
std::function<char(const char)> transform) {
std::string s;
for (size_t i = 0; i < input.length(); i++) { s += transform(input[i]); }
return s;
@@ -142,7 +144,10 @@ std::string CamelToSnake(const std::string &input) {
} else if (!islower(input[i])) {
// Prevent duplicate underscores for Upper_Snake_Case strings
// and UPPERCASE strings.
if (islower(input[i - 1]) || (isdigit(input[i-1]) && !isdigit(input[i]))) { s += '_'; }
if (islower(input[i - 1]) ||
(isdigit(input[i - 1]) && !isdigit(input[i]))) {
s += '_';
}
s += CharToLower(input[i]);
} else {
s += input[i];
@@ -184,7 +189,6 @@ std::string ToDasher(const std::string &input) {
return s;
}
// Converts foo_bar_123baz_456 to foo_bar123_baz456
std::string SnakeToSnake2(const std::string &s) {
if (s.length() <= 1) return s;
@@ -206,8 +210,7 @@ std::string SnakeToSnake2(const std::string &s) {
return result;
}
} // namespace
} // namespace
bool LoadFile(const char *name, bool binary, std::string *buf) {
FLATBUFFERS_ASSERT(g_load_file_function);