forked from BigfootDev/flatbuffers
Merge branch 'master' into master
This commit is contained in:
+28
-7
@@ -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",
|
||||
|
||||
@@ -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 ®ion,
|
||||
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 §ion,
|
||||
// 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
@@ -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
@@ -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_;
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -21,7 +21,7 @@
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
std::unique_ptr<CodeGenerator> NewFBSCodeGenerator();
|
||||
std::unique_ptr<CodeGenerator> NewFBSCodeGenerator(bool no_log = false);
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
|
||||
+4
-5
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user