Merge commit '7b04dc15c5745e780ff19aaff3d43aa1c6c99ad6' into master
Upgrade flatbuffers to the latest. It has been a while.
Change-Id: I6c56d742469591f31bd54243ec6d12c4cf397b26
Signed-off-by: Austin Schuh <austin.schuh@bluerivertech.com>
diff --git a/third_party/flatbuffers/src/BUILD.bazel b/third_party/flatbuffers/src/BUILD.bazel
index d8bbfcd..b01551d 100644
--- a/third_party/flatbuffers/src/BUILD.bazel
+++ b/third_party/flatbuffers/src/BUILD.bazel
@@ -34,10 +34,16 @@
cc_library(
name = "flatc_library",
srcs = [
+ "annotated_binary_text_gen.cpp",
+ "annotated_binary_text_gen.h",
"bfbs_gen.h",
"bfbs_gen_lua.cpp",
"bfbs_gen_lua.h",
+ "bfbs_namer.h",
+ "binary_annotator.cpp",
+ "binary_annotator.h",
"flatc.cpp",
+ "namer.h",
],
hdrs = [
"//:flatc_headers",
@@ -56,6 +62,7 @@
"bfbs_gen.h",
"bfbs_gen_lua.cpp",
"bfbs_gen_lua.h",
+ "bfbs_namer.h",
"flatc_main.cpp",
"idl_gen_cpp.cpp",
"idl_gen_csharp.cpp",
@@ -73,6 +80,7 @@
"idl_gen_swift.cpp",
"idl_gen_text.cpp",
"idl_gen_ts.cpp",
+ "idl_namer.h",
"namer.h",
"util.cpp",
],
diff --git a/third_party/flatbuffers/src/annotated_binary_text_gen.cpp b/third_party/flatbuffers/src/annotated_binary_text_gen.cpp
new file mode 100644
index 0000000..ec30b1d
--- /dev/null
+++ b/third_party/flatbuffers/src/annotated_binary_text_gen.cpp
@@ -0,0 +1,439 @@
+#include "annotated_binary_text_gen.h"
+
+#include <sstream>
+#include <string>
+
+#include "binary_annotator.h"
+#include "flatbuffers/base.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+namespace {
+
+struct OutputConfig {
+ size_t largest_type_string = 10;
+
+ size_t largest_value_string = 20;
+
+ size_t max_bytes_per_line = 8;
+
+ size_t offset_max_char = 4;
+
+ char delimiter = '|';
+};
+
+static std::string ToString(const BinarySectionType type) {
+ switch (type) {
+ case BinarySectionType::Header: return "header";
+ case BinarySectionType::Table: return "table";
+ case BinarySectionType::RootTable: return "root_table";
+ case BinarySectionType::VTable: return "vtable";
+ case BinarySectionType::Struct: return "struct";
+ case BinarySectionType::String: return "string";
+ case BinarySectionType::Vector: return "vector";
+ case BinarySectionType::Unknown: return "unknown";
+ case BinarySectionType::Union: return "union";
+ case BinarySectionType::Padding: return "padding";
+ default: return "todo";
+ }
+}
+
+static bool IsOffset(const BinaryRegionType type) {
+ return type == BinaryRegionType::UOffset || type == BinaryRegionType::SOffset;
+}
+
+template<typename T> std::string ToString(T value) {
+ if (std::is_floating_point<T>::value) {
+ std::stringstream ss;
+ ss << value;
+ return ss.str();
+ } else {
+ return std::to_string(value);
+ }
+}
+
+template<typename T>
+std::string ToValueString(const BinaryRegion ®ion, const uint8_t *binary) {
+ std::string s;
+ s += "0x";
+ const T val = ReadScalar<T>(binary + region.offset);
+ const uint64_t start_index = region.offset + region.length - 1;
+ for (uint64_t i = 0; i < region.length; ++i) {
+ s += ToHex(binary[start_index - i]);
+ }
+ s += " (";
+ s += ToString(val);
+ s += ")";
+ return s;
+}
+
+template<>
+std::string ToValueString<std::string>(const BinaryRegion ®ion,
+ const uint8_t *binary) {
+ return std::string(reinterpret_cast<const char *>(binary + region.offset),
+ static_cast<size_t>(region.array_length));
+}
+
+static std::string ToValueString(const BinaryRegion ®ion,
+ const uint8_t *binary,
+ const OutputConfig &output_config) {
+ std::string s;
+
+ if (region.array_length) {
+ if (region.type == BinaryRegionType::Uint8 ||
+ region.type == BinaryRegionType::Unknown) {
+ // Interpet each value as a ASCII to aid debugging
+ for (uint64_t i = 0; i < region.array_length; ++i) {
+ const uint8_t c = *(binary + region.offset + i);
+ s += isprint(c) ? static_cast<char>(c & 0x7F) : '.';
+ }
+ return s;
+ } else if (region.type == BinaryRegionType::Char) {
+ // string value
+ return ToValueString<std::string>(region, binary);
+ }
+ }
+
+ switch (region.type) {
+ case BinaryRegionType::Uint32:
+ return ToValueString<uint32_t>(region, binary);
+ case BinaryRegionType::Int32: return ToValueString<int32_t>(region, binary);
+ case BinaryRegionType::Uint16:
+ return ToValueString<uint16_t>(region, binary);
+ case BinaryRegionType::Int16: return ToValueString<int16_t>(region, binary);
+ case BinaryRegionType::Bool: return ToValueString<bool>(region, binary);
+ case BinaryRegionType::Uint8: return ToValueString<uint8_t>(region, binary);
+ case BinaryRegionType::Char: return ToValueString<char>(region, binary);
+ case BinaryRegionType::Byte:
+ case BinaryRegionType::Int8: return ToValueString<int8_t>(region, binary);
+ case BinaryRegionType::Int64: return ToValueString<int64_t>(region, binary);
+ case BinaryRegionType::Uint64:
+ return ToValueString<uint64_t>(region, binary);
+ case BinaryRegionType::Double: return ToValueString<double>(region, binary);
+ case BinaryRegionType::Float: return ToValueString<float>(region, binary);
+ case BinaryRegionType::UType: return ToValueString<uint8_t>(region, binary);
+
+ // Handle Offsets separately, incase they add additional details.
+ case BinaryRegionType::UOffset:
+ s += ToValueString<uint32_t>(region, binary);
+ break;
+ case BinaryRegionType::SOffset:
+ s += ToValueString<int32_t>(region, binary);
+ break;
+ case BinaryRegionType::VOffset:
+ s += ToValueString<uint16_t>(region, binary);
+ break;
+
+ default: break;
+ }
+ // If this is an offset type, include the calculated offset location in the
+ // value.
+ // TODO(dbaileychess): It might be nicer to put this in the comment field.
+ if (IsOffset(region.type)) {
+ s += " Loc: +0x";
+ s += ToHex(region.points_to_offset, output_config.offset_max_char);
+ }
+ return s;
+}
+
+struct DocContinuation {
+ // The start column where the value text first starts
+ size_t value_start_column = 0;
+
+ // The remaining part of the doc to print.
+ std::string value;
+};
+
+static std::string GenerateTypeString(const BinaryRegion ®ion) {
+ return ToString(region.type) +
+ ((region.array_length)
+ ? "[" + std::to_string(region.array_length) + "]"
+ : "");
+}
+
+static std::string GenerateComment(const BinaryRegionComment &comment,
+ const BinarySection &) {
+ std::string s;
+ switch (comment.type) {
+ case BinaryRegionCommentType::Unknown: s = "unknown"; break;
+ case BinaryRegionCommentType::SizePrefix: s = "size prefix"; break;
+ case BinaryRegionCommentType::RootTableOffset:
+ s = "offset to root table `" + comment.name + "`";
+ break;
+ // TODO(dbaileychess): make this lowercase to follow the convention.
+ case BinaryRegionCommentType::FileIdentifier: s = "File Identifier"; break;
+ case BinaryRegionCommentType::Padding: s = "padding"; break;
+ case BinaryRegionCommentType::VTableSize: s = "size of this vtable"; break;
+ case BinaryRegionCommentType::VTableRefferingTableLength:
+ s = "size of referring table";
+ break;
+ case BinaryRegionCommentType::VTableFieldOffset:
+ s = "offset to field `" + comment.name;
+ break;
+ case BinaryRegionCommentType::VTableUnknownFieldOffset:
+ s = "offset to unknown field (id: " + std::to_string(comment.index) + ")";
+ break;
+
+ case BinaryRegionCommentType::TableVTableOffset:
+ s = "offset to vtable";
+ break;
+ case BinaryRegionCommentType::TableField:
+ s = "table field `" + comment.name;
+ break;
+ case BinaryRegionCommentType::TableUnknownField: s = "unknown field"; break;
+ case BinaryRegionCommentType::TableOffsetField:
+ s = "offset to field `" + comment.name + "`";
+ break;
+ case BinaryRegionCommentType::StructField:
+ s = "struct field `" + comment.name + "`";
+ break;
+ case BinaryRegionCommentType::ArrayField:
+ s = "array field `" + comment.name + "`[" +
+ std::to_string(comment.index) + "]";
+ break;
+ case BinaryRegionCommentType::StringLength: s = "length of string"; break;
+ case BinaryRegionCommentType::StringValue: s = "string literal"; break;
+ case BinaryRegionCommentType::StringTerminator:
+ s = "string terminator";
+ break;
+ case BinaryRegionCommentType::VectorLength:
+ s = "length of vector (# items)";
+ break;
+ case BinaryRegionCommentType::VectorValue:
+ s = "value[" + std::to_string(comment.index) + "]";
+ break;
+ case BinaryRegionCommentType::VectorTableValue:
+ s = "offset to table[" + std::to_string(comment.index) + "]";
+ break;
+ case BinaryRegionCommentType::VectorStringValue:
+ s = "offset to string[" + std::to_string(comment.index) + "]";
+ break;
+ case BinaryRegionCommentType::VectorUnionValue:
+ s = "offset to union[" + std::to_string(comment.index) + "]";
+ break;
+
+ default: break;
+ }
+ if (!comment.default_value.empty()) { s += " " + comment.default_value; }
+
+ switch (comment.status) {
+ case BinaryRegionStatus::OK: break; // no-op
+ case BinaryRegionStatus::WARN: s = "WARN: " + s; break;
+ case BinaryRegionStatus::WARN_NO_REFERENCES:
+ s = "WARN: nothing refers to this section.";
+ break;
+ case BinaryRegionStatus::WARN_CORRUPTED_PADDING:
+ s = "WARN: could be corrupted padding region.";
+ break;
+ case BinaryRegionStatus::WARN_PADDING_LENGTH:
+ s = "WARN: padding is longer than expected.";
+ break;
+ case BinaryRegionStatus::ERROR: s = "ERROR: " + s; break;
+ case BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY:
+ s = "ERROR: " + s + ". Invalid offset, points outside the binary.";
+ break;
+ case BinaryRegionStatus::ERROR_INCOMPLETE_BINARY:
+ s = "ERROR: " + s + ". Incomplete binary, expected to read " +
+ comment.status_message + " bytes.";
+ break;
+ case BinaryRegionStatus::ERROR_LENGTH_TOO_LONG:
+ s = "ERROR: " + s + ". Longer than the binary.";
+ break;
+ case BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT:
+ s = "ERROR: " + s + ". Shorter than the minimum length: ";
+ break;
+ case BinaryRegionStatus::ERROR_REQUIRED_FIELD_NOT_PRESENT:
+ s = "ERROR: " + s + ". Required field is not present.";
+ break;
+ case BinaryRegionStatus::ERROR_INVALID_UNION_TYPE:
+ s = "ERROR: " + s + ". Invalid union type value.";
+ break;
+ case BinaryRegionStatus::ERROR_CYCLE_DETECTED:
+ s = "ERROR: " + s + ". Invalid offset, cycle detected.";
+ break;
+ }
+
+ return s;
+}
+
+static std::string GenerateDocumentation(const BinaryRegion ®ion,
+ const BinarySection §ion,
+ const uint8_t *binary,
+ DocContinuation &continuation,
+ const OutputConfig &output_config) {
+ std::string s;
+
+ // Check if there is a doc continuation that should be prioritized.
+ if (continuation.value_start_column) {
+ s += std::string(continuation.value_start_column - 2, ' ');
+ s += output_config.delimiter;
+ s += " ";
+
+ s += continuation.value.substr(0, output_config.max_bytes_per_line);
+ continuation.value = continuation.value.substr(
+ std::min(output_config.max_bytes_per_line, continuation.value.size()));
+ return s;
+ }
+
+ {
+ std::stringstream ss;
+ ss << std::setw(output_config.largest_type_string) << std::left;
+ ss << GenerateTypeString(region);
+ s += ss.str();
+ }
+ s += " ";
+ s += output_config.delimiter;
+ s += " ";
+ if (region.array_length) {
+ // Record where the value is first being outputted.
+ continuation.value_start_column = s.size();
+
+ // Get the full-length value, which we will chunk below.
+ const std::string value = ToValueString(region, binary, output_config);
+
+ std::stringstream ss;
+ ss << std::setw(output_config.largest_value_string) << std::left;
+ ss << value.substr(0, output_config.max_bytes_per_line);
+ s += ss.str();
+
+ continuation.value =
+ value.substr(std::min(output_config.max_bytes_per_line, value.size()));
+ } else {
+ std::stringstream ss;
+ ss << std::setw(output_config.largest_value_string) << std::left;
+ ss << ToValueString(region, binary, output_config);
+ s += ss.str();
+ }
+
+ s += " ";
+ s += output_config.delimiter;
+ s += " ";
+ s += GenerateComment(region.comment, section);
+
+ return s;
+}
+
+static std::string GenerateRegion(const BinaryRegion ®ion,
+ const BinarySection §ion,
+ const uint8_t *binary,
+ const OutputConfig &output_config) {
+ std::string s;
+ bool doc_generated = false;
+ DocContinuation doc_continuation;
+ for (uint64_t i = 0; i < region.length; ++i) {
+ if ((i % output_config.max_bytes_per_line) == 0) {
+ // Start a new line of output
+ s += '\n';
+ s += " ";
+ s += "+0x";
+ s += ToHex(region.offset + i, output_config.offset_max_char);
+ s += " ";
+ s += output_config.delimiter;
+ }
+
+ // Add each byte
+ s += " ";
+ s += ToHex(binary[region.offset + i]);
+
+ // Check for end of line or end of region conditions.
+ if (((i + 1) % output_config.max_bytes_per_line == 0) ||
+ i + 1 == region.length) {
+ if (i + 1 == region.length) {
+ // We are out of bytes but haven't the kMaxBytesPerLine, so we need to
+ // zero those out to align everything globally.
+ for (uint64_t j = i + 1; (j % output_config.max_bytes_per_line) != 0;
+ ++j) {
+ s += " ";
+ }
+ }
+ s += " ";
+ s += output_config.delimiter;
+ // This is the end of the first line or its the last byte of the region,
+ // generate the end-of-line documentation.
+ if (!doc_generated) {
+ s += " ";
+ s += GenerateDocumentation(region, section, binary, doc_continuation,
+ output_config);
+
+ // If we have a value in the doc continuation, that means the doc is
+ // being printed on multiple lines.
+ doc_generated = doc_continuation.value.empty();
+ }
+ }
+ }
+
+ return s;
+}
+
+static std::string GenerateSection(const BinarySection §ion,
+ const uint8_t *binary,
+ const OutputConfig &output_config) {
+ std::string s;
+ s += "\n";
+ s += ToString(section.type);
+ if (!section.name.empty()) { s += " (" + section.name + ")"; }
+ s += ":";
+ for (const BinaryRegion ®ion : section.regions) {
+ s += GenerateRegion(region, section, binary, output_config);
+ }
+ return s;
+}
+} // namespace
+
+bool AnnotatedBinaryTextGenerator::Generate(
+ const std::string &filename, const std::string &schema_filename) {
+ OutputConfig output_config;
+ output_config.max_bytes_per_line = options_.max_bytes_per_line;
+
+ // Given the length of the binary, we can calculate the maximum number of
+ // characters to display in the offset hex: (i.e. 2 would lead to 0XFF being
+ // the max output).
+ output_config.offset_max_char =
+ binary_length_ > 0xFFFFFF
+ ? 8
+ : (binary_length_ > 0xFFFF ? 6 : (binary_length_ > 0xFF ? 4 : 2));
+
+ // Find the largest type string of all the regions in this file, so we can
+ // align the output nicely.
+ output_config.largest_type_string = 0;
+ for (const auto §ion : annotations_) {
+ for (const auto ®ion : section.second.regions) {
+ std::string s = GenerateTypeString(region);
+ if (s.size() > output_config.largest_type_string) {
+ output_config.largest_type_string = s.size();
+ }
+
+ // Don't consider array regions, as they will be split to multiple lines.
+ if (!region.array_length) {
+ s = ToValueString(region, binary_, output_config);
+ if (s.size() > output_config.largest_value_string) {
+ output_config.largest_value_string = s.size();
+ }
+ }
+ }
+ }
+
+ // Generate each of the binary sections
+ std::string s;
+
+ s += "// Annotated Flatbuffer Binary\n";
+ s += "//\n";
+ s += "// Schema file: " + schema_filename + "\n";
+ s += "// Binary file: " + filename + "\n";
+
+ for (const auto §ion : annotations_) {
+ s += GenerateSection(section.second, binary_, output_config);
+ s += "\n";
+ }
+
+ // Modify the output filename.
+ std::string output_filename = StripExtension(filename);
+ output_filename += options_.output_postfix;
+ output_filename +=
+ "." + (options_.output_extension.empty() ? GetExtension(filename)
+ : options_.output_extension);
+
+ return SaveFile(output_filename.c_str(), s, false);
+}
+
+} // namespace flatbuffers
diff --git a/third_party/flatbuffers/src/annotated_binary_text_gen.h b/third_party/flatbuffers/src/annotated_binary_text_gen.h
new file mode 100644
index 0000000..712c452
--- /dev/null
+++ b/third_party/flatbuffers/src/annotated_binary_text_gen.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2021 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_ANNOTATED_BINARY_TEXT_GEN_H_
+#define FLATBUFFERS_ANNOTATED_BINARY_TEXT_GEN_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "binary_annotator.h"
+
+namespace flatbuffers {
+
+class AnnotatedBinaryTextGenerator {
+ public:
+ struct Options {
+ // The maximum number of raw bytes to print per line in the output. 8 is a
+ // good default due to the largest type (double) being 8 bytes long.
+ size_t max_bytes_per_line = 8;
+
+ // The output file postfix, appended between the filename and the extension.
+ // Example binary1.bin -> binary1_annotated.bin
+ std::string output_postfix = "";
+
+ // The output file extension, replacing any extension given. If empty, don't
+ // change the provided extension. AFB = Annotated Flatbuffer Binary
+ //
+ // Example: binary1.bin -> binary1.afb
+ std::string output_extension = "afb";
+ };
+
+ explicit AnnotatedBinaryTextGenerator(
+ const Options &options, std::map<uint64_t, BinarySection> annotations,
+ const uint8_t *const binary, const int64_t binary_length)
+ : annotations_(std::move(annotations)),
+ binary_(binary),
+ binary_length_(binary_length),
+ options_(options) {}
+
+ // Generate the annotated binary for the given `filename`. Returns true if the
+ // annotated binary was successfully saved.
+ bool Generate(const std::string &filename,
+ const std::string &schema_filename);
+
+ private:
+ const std::map<uint64_t, BinarySection> annotations_;
+
+ // The binary data itself.
+ const uint8_t *binary_;
+ const int64_t binary_length_;
+
+ // Output configuration
+ const Options options_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_ANNOTATED_BINARY_TEXT_GEN_H_
diff --git a/third_party/flatbuffers/src/bfbs_gen.h b/third_party/flatbuffers/src/bfbs_gen.h
index 27baef9..63220e8 100644
--- a/third_party/flatbuffers/src/bfbs_gen.h
+++ b/third_party/flatbuffers/src/bfbs_gen.h
@@ -24,19 +24,21 @@
namespace flatbuffers {
-void ForAllEnums(
+namespace {
+
+static void ForAllEnums(
const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums,
std::function<void(const reflection::Enum *)> func) {
for (auto it = enums->cbegin(); it != enums->cend(); ++it) { func(*it); }
}
-void ForAllObjects(
+static void ForAllObjects(
const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects,
std::function<void(const reflection::Object *)> func) {
for (auto it = objects->cbegin(); it != objects->cend(); ++it) { func(*it); }
}
-void ForAllEnumValues(const reflection::Enum *enum_def,
+static void ForAllEnumValues(const reflection::Enum *enum_def,
std::function<void(const reflection::EnumVal *)> func) {
for (auto it = enum_def->values()->cbegin(); it != enum_def->values()->cend();
++it) {
@@ -44,7 +46,7 @@
}
}
-void ForAllDocumentation(
+static void ForAllDocumentation(
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
*documentation,
std::function<void(const flatbuffers::String *)> func) {
@@ -73,10 +75,6 @@
return base_type == reflection::BaseType::Obj;
}
-static bool IsScalar(const reflection::BaseType base_type) {
- return base_type >= reflection::BaseType::UType && base_type <= reflection::BaseType::Double;
-}
-
static bool IsFloatingPoint(const reflection::BaseType base_type) {
return base_type == reflection::BaseType::Float || base_type == reflection::BaseType::Double;
}
@@ -93,21 +91,7 @@
return base_type == reflection::BaseType::Vector;
}
-static std::string Denamespace(const flatbuffers::String *name,
- std::string &ns) {
- const size_t pos = name->str().find_last_of('.');
- if (pos == std::string::npos) {
- ns = "";
- return name->str();
- }
- ns = name->str().substr(0, pos);
- return name->str().substr(pos + 1);
-}
-
-static std::string Denamespace(const flatbuffers::String *name) {
- std::string ns;
- return Denamespace(name, ns);
-}
+} // namespace
// A concrete base Flatbuffer Generator that specific language generators can
// derive from.
diff --git a/third_party/flatbuffers/src/bfbs_gen_lua.cpp b/third_party/flatbuffers/src/bfbs_gen_lua.cpp
index 18e171c..e9623d4 100644
--- a/third_party/flatbuffers/src/bfbs_gen_lua.cpp
+++ b/third_party/flatbuffers/src/bfbs_gen_lua.cpp
@@ -25,9 +25,11 @@
// Ensure no includes to flatc internals. bfbs_gen.h and generator.h are OK.
#include "bfbs_gen.h"
+#include "bfbs_namer.h"
#include "flatbuffers/bfbs_generator.h"
// The intermediate representation schema.
+#include "flatbuffers/reflection.h"
#include "flatbuffers/reflection_generated.h"
namespace flatbuffers {
@@ -36,6 +38,36 @@
// To reduce typing
namespace r = ::reflection;
+std::set<std::string> LuaKeywords() {
+ return { "and", "break", "do", "else", "elseif", "end",
+ "false", "for", "function", "goto", "if", "in",
+ "local", "nil", "not", "or", "repeat", "return",
+ "then", "true", "until", "while" };
+}
+
+Namer::Config LuaDefaultConfig() {
+ return { /*types=*/Case::kUpperCamel,
+ /*constants=*/Case::kUnknown,
+ /*methods=*/Case::kUpperCamel,
+ /*functions=*/Case::kUpperCamel,
+ /*fields=*/Case::kUpperCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/"",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"__",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"",
+ /*filename_extension=*/".lua" };
+}
+
class LuaBfbsGenerator : public BaseBfbsGenerator {
public:
explicit LuaBfbsGenerator(const std::string &flatc_version)
@@ -44,14 +76,8 @@
requires_(),
current_obj_(nullptr),
current_enum_(nullptr),
- flatc_version_(flatc_version) {
- 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));
- }
+ flatc_version_(flatc_version),
+ namer_(LuaDefaultConfig(), LuaKeywords()) {}
GeneratorStatus GenerateFromSchema(const r::Schema *schema)
FLATBUFFERS_OVERRIDE {
@@ -76,14 +102,14 @@
std::string ns;
const std::string enum_name =
- NormalizeName(Denamespace(enum_def->name(), ns));
+ namer_.Type(namer_.Denamespace(enum_def, ns));
GenerateDocumentation(enum_def->documentation(), "", code);
code += "local " + enum_name + " = {\n";
ForAllEnumValues(enum_def, [&](const reflection::EnumVal *enum_val) {
GenerateDocumentation(enum_val->documentation(), " ", code);
- code += " " + NormalizeName(enum_val->name()) + " = " +
+ code += " " + namer_.Variant(enum_val->name()->str()) + " = " +
NumToString(enum_val->value()) + ",\n";
});
code += "}\n";
@@ -107,7 +133,7 @@
std::string ns;
const std::string object_name =
- NormalizeName(Denamespace(object->name(), ns));
+ namer_.Type(namer_.Denamespace(object, ns));
GenerateDocumentation(object->documentation(), "", code);
@@ -149,14 +175,12 @@
// Skip writing deprecated fields altogether.
if (field->deprecated()) { return; }
- const std::string field_name = NormalizeName(field->name());
- const std::string field_name_camel_case =
- ConvertCase(field_name, Case::kUpperCamel);
+ const std::string field_name = namer_.Field(field->name()->str());
const r::BaseType base_type = field->type()->base_type();
// Generate some fixed strings so we don't repeat outselves later.
const std::string getter_signature =
- "function mt:" + field_name_camel_case + "()\n";
+ "function mt:" + field_name + "()\n";
const std::string offset_prefix = "local o = self.view:Offset(" +
NumToString(field->offset()) + ")\n";
const std::string offset_prefix_2 = "if o ~= 0 then\n";
@@ -201,7 +225,7 @@
}
case r::BaseType::Obj: {
if (object->is_struct()) {
- code += "function mt:" + field_name_camel_case + "(obj)\n";
+ code += "function mt:" + field_name + "(obj)\n";
code += " obj:Init(self.view.bytes, self.view.pos + " +
NumToString(field->offset()) + ")\n";
code += " return obj\n";
@@ -252,7 +276,7 @@
case r::BaseType::Vector: {
const r::BaseType vector_base_type = field->type()->element();
int32_t element_size = field->type()->element_size();
- code += "function mt:" + field_name_camel_case + "(j)\n";
+ code += "function mt:" + field_name + "(j)\n";
code += " " + offset_prefix;
code += " " + offset_prefix_2;
@@ -297,8 +321,7 @@
// generate a helper function to get it as a byte string in
// Lua.
if (IsSingleByte(vector_base_type)) {
- code += "function mt:" + field_name_camel_case +
- "AsString(start, stop)\n";
+ code += "function mt:" + field_name + "AsString(start, stop)\n";
code += " return self.view:VectorAsString(" +
NumToString(field->offset()) + ", start, stop)\n";
code += "end\n";
@@ -307,7 +330,7 @@
// We also make a new accessor to query just the length of the
// vector.
- code += "function mt:" + field_name_camel_case + "Length()\n";
+ code += "function mt:" + field_name + "Length()\n";
code += " " + offset_prefix;
code += " " + offset_prefix_2;
code += " return self.view:VectorLen(o)\n";
@@ -344,21 +367,20 @@
ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
if (field->deprecated()) { return; }
- const std::string field_name = NormalizeName(field->name());
+ const std::string field_name = namer_.Field(field->name()->str());
+ const std::string variable_name =
+ namer_.Variable(field->name()->str());
- code += "function " + object_name + ".Add" +
- ConvertCase(field_name, Case::kUpperCamel) + "(builder, " +
- ConvertCase(field_name, Case::kLowerCamel) + ")\n";
+ code += "function " + object_name + ".Add" + field_name +
+ "(builder, " + variable_name + ")\n";
code += " builder:Prepend" + GenerateMethod(field) + "Slot(" +
- NumToString(field->id()) + ", " +
- ConvertCase(field_name, Case::kLowerCamel) + ", " +
+ NumToString(field->id()) + ", " + variable_name + ", " +
DefaultValue(field) + ")\n";
code += "end\n";
code += "\n";
if (IsVector(field->type()->base_type())) {
- code += "function " + object_name + ".Start" +
- ConvertCase(field_name, Case::kUpperCamel) +
+ code += "function " + object_name + ".Start" + field_name +
"Vector(builder, numElems)\n";
const int32_t element_size = field->type()->element_size();
@@ -406,11 +428,9 @@
if (IsStructOrTable(field->type()->base_type())) {
const r::Object *field_object = GetObject(field->type());
signature += GenerateStructBuilderArgs(
- field_object, prefix + NormalizeName(field->name()) + "_");
+ field_object, prefix + namer_.Variable(field->name()->str()) + "_");
} else {
- signature +=
- ", " + prefix +
- ConvertCase(NormalizeName(field->name()), Case::kLowerCamel);
+ signature += ", " + prefix + namer_.Variable(field->name()->str());
}
});
return signature;
@@ -432,11 +452,10 @@
if (IsStructOrTable(field->type()->base_type())) {
const r::Object *field_object = GetObject(field->type());
code += AppendStructBuilderBody(
- field_object, prefix + NormalizeName(field->name()) + "_");
+ field_object, prefix + namer_.Variable(field->name()->str()) + "_");
} else {
code += " builder:Prepend" + GenerateMethod(field) + "(" + prefix +
- ConvertCase(NormalizeName(field->name()), Case::kLowerCamel) +
- ")\n";
+ namer_.Variable(field->name()->str()) + ")\n";
}
});
@@ -445,9 +464,7 @@
std::string GenerateMethod(const r::Field *field) const {
const r::BaseType base_type = field->type()->base_type();
- if (IsScalar(base_type)) {
- return ConvertCase(GenerateType(base_type), Case::kUpperCamel);
- }
+ if (IsScalar(base_type)) { return namer_.Type(GenerateType(base_type)); }
if (IsStructOrTable(base_type)) { return "Struct"; }
return "UOffsetTRelative";
}
@@ -460,9 +477,7 @@
case r::BaseType::Vector: return GenerateGetter(type, true);
default:
return "self.view:Get(flatbuffers.N." +
- ConvertCase(GenerateType(type, element_type),
- Case::kUpperCamel) +
- ", ";
+ namer_.Type(GenerateType(type, element_type)) + ", ";
}
}
@@ -474,10 +489,8 @@
switch (base_type) {
case r::BaseType::String: return "string";
case r::BaseType::Vector: return GenerateGetter(type, true);
- case r::BaseType::Obj: {
- const r::Object *obj = GetObject(type);
- return NormalizeName(Denamespace(obj->name()));
- };
+ case r::BaseType::Obj: return namer_.Type(namer_.Denamespace(GetObject(type)));
+
default: return "*flatbuffers.Table";
}
}
@@ -515,14 +528,6 @@
return "0";
}
- std::string NormalizeName(const std::string name) const {
- return keywords_.find(name) == keywords_.end() ? name : "_" + name;
- }
-
- std::string NormalizeName(const flatbuffers::String *name) const {
- return NormalizeName(name->str());
- }
-
void StartCodeBlock(const reflection::Enum *enum_def) {
current_enum_ = enum_def;
current_obj_ = nullptr;
@@ -544,11 +549,11 @@
if (IsStructOrTable(type)) {
const r::Object *object = GetObjectByIndex(field->type()->index());
- if (object == current_obj_) { return Denamespace(object->name()); }
+ if (object == current_obj_) { return namer_.Denamespace(object); }
type_name = object->name()->str();
} else {
const r::Enum *enum_def = GetEnumByIndex(field->type()->index());
- if (enum_def == current_enum_) { return Denamespace(enum_def->name()); }
+ if (enum_def == current_enum_) { return namer_.Denamespace(enum_def); }
type_name = enum_def->name()->str();
}
@@ -600,7 +605,7 @@
// Namespaces are '.' deliminted, so replace it with the path separator.
std::string path = ns;
- if (path.empty()) {
+ if (ns.empty()) {
path = ".";
} else {
std::replace(path.begin(), path.end(), '.', '/');
@@ -608,7 +613,7 @@
// TODO(derekbailey): figure out a save file without depending on util.h
EnsureDirExists(path);
- const std::string file_name = path + "/" + name + ".lua";
+ const std::string file_name = path + "/" + namer_.File(name);
SaveFile(file_name.c_str(), code, false);
}
@@ -617,6 +622,7 @@
const r::Object *current_obj_;
const r::Enum *current_enum_;
const std::string flatc_version_;
+ const BfbsNamer namer_;
};
} // namespace
diff --git a/third_party/flatbuffers/src/bfbs_namer.h b/third_party/flatbuffers/src/bfbs_namer.h
new file mode 100644
index 0000000..2c6e724
--- /dev/null
+++ b/third_party/flatbuffers/src/bfbs_namer.h
@@ -0,0 +1,43 @@
+#ifndef FLATBUFFERS_BFBS_NAMER
+#define FLATBUFFERS_BFBS_NAMER
+
+#include "flatbuffers/reflection.h"
+#include "namer.h"
+
+namespace flatbuffers {
+
+// Provides Namer capabilities to types defined in the flatbuffers reflection.
+class BfbsNamer : public Namer {
+ public:
+ explicit BfbsNamer(Config config, std::set<std::string> keywords)
+ : Namer(config, std::move(keywords)) {}
+
+ using Namer::Constant;
+ using Namer::Denamespace;
+ using Namer::Directories;
+ using Namer::Field;
+ using Namer::File;
+ using Namer::Function;
+ using Namer::Method;
+ using Namer::Namespace;
+ using Namer::NamespacedType;
+ using Namer::ObjectType;
+ using Namer::Type;
+ using Namer::Variable;
+ using Namer::Variant;
+
+ template<typename T>
+ std::string Denamespace(T t, std::string &namespace_prefix,
+ const char delimiter = '.') const {
+ return Namer::Denamespace(t->name()->c_str(), namespace_prefix, delimiter);
+ }
+
+ template<typename T>
+ std::string Denamespace(T t, const char delimiter = '.') const {
+ return Namer::Denamespace(t->name()->c_str(), delimiter);
+ }
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BFBS_NAMER
\ No newline at end of file
diff --git a/third_party/flatbuffers/src/binary_annotator.cpp b/third_party/flatbuffers/src/binary_annotator.cpp
new file mode 100644
index 0000000..dd0b454
--- /dev/null
+++ b/third_party/flatbuffers/src/binary_annotator.cpp
@@ -0,0 +1,1419 @@
+#include "binary_annotator.h"
+
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "flatbuffers/reflection.h"
+#include "flatbuffers/verifier.h"
+
+namespace flatbuffers {
+namespace {
+
+static bool BinaryRegionSort(const BinaryRegion &a, const BinaryRegion &b) {
+ return a.offset < b.offset;
+}
+
+static void SetError(BinaryRegionComment &comment, BinaryRegionStatus status,
+ std::string message = "") {
+ comment.status = status;
+ comment.status_message = message;
+}
+
+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 = {}) {
+ BinaryRegion region;
+ region.offset = offset;
+ region.length = length;
+ region.type = type;
+ region.array_length = array_length;
+ region.points_to_offset = points_to_offset;
+ region.comment = std::move(comment);
+ return region;
+}
+
+static BinarySection MakeBinarySection(
+ const std::string &name, const BinarySectionType type,
+ const std::vector<BinaryRegion> regions) {
+ BinarySection section;
+ section.name = name;
+ section.type = type;
+ section.regions = std::move(regions);
+ return section;
+}
+
+static BinarySection MakeSingleRegionBinarySection(const std::string &name,
+ const BinarySectionType type,
+ const BinaryRegion ®ion) {
+ std::vector<BinaryRegion> regions;
+ regions.push_back(region);
+ return MakeBinarySection(name, type, std::move(regions));
+}
+
+static bool IsNonZeroRegion(const uint64_t offset, const uint64_t length,
+ const uint8_t *const binary) {
+ for (uint64_t i = offset; i < offset + length; ++i) {
+ if (binary[i] != 0) { return true; }
+ }
+ return false;
+}
+
+static bool IsPrintableRegion(const uint64_t offset, const uint64_t length,
+ const uint8_t *const binary) {
+ for (uint64_t i = offset; i < offset + length; ++i) {
+ if (!isprint(binary[i])) { return false; }
+ }
+ return true;
+}
+
+static BinarySection GenerateMissingSection(const uint64_t offset,
+ const uint64_t length,
+ const uint8_t *const binary) {
+ std::vector<BinaryRegion> regions;
+
+ // Check if the region is all zeros or not, as that can tell us if it is
+ // padding or not.
+ if (IsNonZeroRegion(offset, length, binary)) {
+ // Some of the padding bytes are non-zero, so this might be an unknown
+ // section of the binary.
+ // TODO(dbaileychess): We could be a bit smarter with different sized
+ // alignments. For now, the 8 byte check encompasses all the smaller
+ // alignments.
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::Unknown;
+ if (length >= 8) {
+ SetError(comment, BinaryRegionStatus::WARN_NO_REFERENCES);
+ } else {
+ SetError(comment, BinaryRegionStatus::WARN_CORRUPTED_PADDING);
+ }
+
+ regions.push_back(MakeBinaryRegion(offset, length * sizeof(uint8_t),
+ BinaryRegionType::Unknown, length, 0,
+ comment));
+
+ return MakeBinarySection("no known references", BinarySectionType::Unknown,
+ std::move(regions));
+ }
+
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::Padding;
+ if (length >= 8) {
+ SetError(comment, BinaryRegionStatus::WARN_PADDING_LENGTH);
+ }
+
+ // This region is most likely padding.
+ regions.push_back(MakeBinaryRegion(offset, length * sizeof(uint8_t),
+ BinaryRegionType::Uint8, length, 0,
+ comment));
+
+ return MakeBinarySection("", BinarySectionType::Padding, std::move(regions));
+}
+
+} // namespace
+
+std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
+ flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_));
+ if (!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 {}; }
+
+ // Make sure we start with a clean slate.
+ vtables_.clear();
+ sections_.clear();
+
+ // First parse the header region which always start at offset 0.
+ // The returned offset will point to the root_table location.
+ const uint64_t root_table_offset = BuildHeader(0);
+
+ if (IsValidOffset(root_table_offset)) {
+ // Build the root table, and all else will be referenced from it.
+ BuildTable(root_table_offset, BinarySectionType::RootTable,
+ schema_->root_table());
+ }
+
+ // Now that all the sections are built, make sure the binary sections are
+ // contiguous.
+ FixMissingRegions();
+
+ // Then scan the area between BinarySections insert padding sections that are
+ // implied.
+ FixMissingSections();
+
+ return sections_;
+}
+
+uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
+ const auto root_table_offset = ReadScalar<uint32_t>(header_offset);
+
+ if (!root_table_offset.has_value()) {
+ // This shouldn't occur, since we validate the min size of the buffer
+ // before. But for completion sake, we shouldn't read passed the binary end.
+ return std::numeric_limits<uint64_t>::max();
+ }
+
+ std::vector<BinaryRegion> regions;
+ uint64_t offset = header_offset;
+ // TODO(dbaileychess): sized prefixed value
+
+ 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())) {
+ 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));
+ offset += sizeof(uint32_t);
+
+ if (IsValidRead(offset, flatbuffers::kFileIdentifierLength) &&
+ IsPrintableRegion(offset, flatbuffers::kFileIdentifierLength, binary_)) {
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::FileIdentifier;
+ // Check if the file identifier region has non-zero data, and assume its
+ // the file identifier. Otherwise, it will get filled in with padding
+ // later.
+ regions.push_back(MakeBinaryRegion(
+ offset, flatbuffers::kFileIdentifierLength * sizeof(uint8_t),
+ BinaryRegionType::Char, flatbuffers::kFileIdentifierLength, 0,
+ comment));
+ }
+
+ AddSection(header_offset, MakeBinarySection("", BinarySectionType::Header,
+ std::move(regions)));
+
+ return root_table_offset.value();
+}
+
+void BinaryAnnotator::BuildVTable(const uint64_t vtable_offset,
+ const reflection::Object *const table,
+ const uint64_t offset_of_referring_table) {
+ // First see if we have used this vtable before, if so skip building it again.
+ auto it = vtables_.find(vtable_offset);
+ if (it != vtables_.end()) { return; }
+
+ if (ContainsSection(vtable_offset)) { return; }
+
+ BinaryRegionComment vtable_size_comment;
+ vtable_size_comment.type = BinaryRegionCommentType::VTableSize;
+
+ const auto vtable_length = ReadScalar<uint16_t>(vtable_offset);
+ if (!vtable_length.has_value()) {
+ const uint64_t remaining = RemainingBytes(vtable_offset);
+
+ SetError(vtable_size_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "2");
+
+ AddSection(vtable_offset,
+ MakeSingleRegionBinarySection(
+ table->name()->str(), BinarySectionType::VTable,
+ MakeBinaryRegion(vtable_offset, remaining,
+ BinaryRegionType::Unknown, remaining, 0,
+ vtable_size_comment)));
+ return;
+ }
+
+ // Vtables start with the size of the vtable
+ const uint16_t vtable_size = vtable_length.value();
+
+ if (!IsValidOffset(vtable_offset + vtable_size - 1)) {
+ SetError(vtable_size_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+ // The vtable_size points to off the end of the binary.
+ AddSection(vtable_offset,
+ MakeSingleRegionBinarySection(
+ table->name()->str(), BinarySectionType::VTable,
+ MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
+ BinaryRegionType::Uint16, 0, 0,
+ vtable_size_comment)));
+
+ return;
+ } else if (vtable_size < 2 * sizeof(uint16_t)) {
+ SetError(vtable_size_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT,
+ "4");
+ // The size includes itself and the table size which are both uint16_t.
+ AddSection(vtable_offset,
+ MakeSingleRegionBinarySection(
+ table->name()->str(), BinarySectionType::VTable,
+ MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
+ BinaryRegionType::Uint16, 0, 0,
+ vtable_size_comment)));
+ return;
+ }
+
+ std::vector<BinaryRegion> regions;
+
+ regions.push_back(MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
+ BinaryRegionType::Uint16, 0, 0,
+ vtable_size_comment));
+ uint64_t offset = vtable_offset + sizeof(uint16_t);
+
+ BinaryRegionComment ref_table_len_comment;
+ ref_table_len_comment.type =
+ BinaryRegionCommentType::VTableRefferingTableLength;
+
+ // Ensure we can read the next uint16_t field, which is the size of the
+ // referring table.
+ const auto table_length = ReadScalar<uint16_t>(offset);
+
+ if (!table_length.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+ SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "2");
+
+ AddSection(offset, MakeSingleRegionBinarySection(
+ table->name()->str(), BinarySectionType::VTable,
+ MakeBinaryRegion(
+ offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, ref_table_len_comment)));
+ return;
+ }
+
+ // Then they have the size of the table they reference.
+ const uint16_t table_size = table_length.value();
+
+ if (!IsValidOffset(offset_of_referring_table + table_size - 1)) {
+ SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+ } else if (table_size < 4) {
+ SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT,
+ "4");
+ }
+
+ regions.push_back(MakeBinaryRegion(offset, sizeof(uint16_t),
+ BinaryRegionType::Uint16, 0, 0,
+ ref_table_len_comment));
+ offset += sizeof(uint16_t);
+
+ const uint64_t offset_start = offset;
+
+ // A mapping between field (and its id) to the relative offset (uin16_t) from
+ // the start of the table.
+ std::map<uint16_t, VTable::Entry> fields;
+
+ // Counter for determining if the binary has more vtable entries than the
+ // schema provided. This can occur if the binary was created at a newer schema
+ // version and is being processed with an older one.
+ uint16_t fields_processed = 0;
+
+ // Loop over all the fields.
+ ForAllFields(table, /*reverse=*/false, [&](const reflection::Field *field) {
+ const uint64_t field_offset = offset_start + field->id() * sizeof(uint16_t);
+
+ if (field_offset >= vtable_offset + vtable_size) {
+ // This field_offset is too large for this vtable, so it must come from a
+ // newer schema than the binary was create with or the binary writer did
+ // not write it. For either case, it is safe to ignore.
+
+ // TODO(dbaileychess): We could show which fields are not set an their
+ // default values if we want. We just need a way to make it obvious that
+ // it isn't part of the buffer.
+ return;
+ }
+
+ BinaryRegionComment field_comment;
+ field_comment.type = BinaryRegionCommentType::VTableFieldOffset;
+ field_comment.name = std::string(field->name()->c_str()) +
+ "` (id: " + std::to_string(field->id()) + ")";
+
+ const auto offset_from_table = ReadScalar<uint16_t>(field_offset);
+
+ if (!offset_from_table.has_value()) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+
+ SetError(field_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, field_comment));
+
+ return;
+ }
+
+ if (!IsValidOffset(offset_of_referring_table + offset_from_table.value() -
+ 1)) {
+ SetError(field_comment, BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+ regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+ BinaryRegionType::VOffset, 0, 0,
+ field_comment));
+ return;
+ }
+
+ VTable::Entry entry;
+ entry.field = field;
+ entry.offset_from_table = offset_from_table.value();
+ fields.insert(std::make_pair(field->id(), entry));
+
+ std::string default_label;
+ if (offset_from_table.value() == 0) {
+ // Not present, so could be default or be optional.
+ if (field->required()) {
+ SetError(field_comment,
+ BinaryRegionStatus::ERROR_REQUIRED_FIELD_NOT_PRESENT);
+ // If this is a required field, make it known this is an error.
+ regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+ BinaryRegionType::VOffset, 0, 0,
+ field_comment));
+ return;
+ } else {
+ // Its an optional field, so get the default value and interpret and
+ // provided an annotation for it.
+ if (IsScalar(field->type()->base_type())) {
+ default_label += "<defaults to ";
+ default_label += IsFloat(field->type()->base_type())
+ ? std::to_string(field->default_real())
+ : std::to_string(field->default_integer());
+ default_label += "> (";
+ } else {
+ default_label += "<null> (";
+ }
+ default_label +=
+ reflection::EnumNameBaseType(field->type()->base_type());
+ default_label += ")";
+ }
+ }
+ field_comment.default_value = default_label;
+
+ regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+ BinaryRegionType::VOffset, 0, 0,
+ field_comment));
+
+ fields_processed++;
+ });
+
+ // Check if we covered all the expectant fields. If not, we need to add them
+ // as unknown fields.
+ uint16_t expectant_vtable_fields =
+ (vtable_size - sizeof(uint16_t) - sizeof(uint16_t)) / sizeof(uint16_t);
+
+ // Prevent a bad binary from declaring a really large vtable_size, that we can
+ // not indpendently verify.
+ expectant_vtable_fields = std::min(
+ static_cast<uint16_t>(fields_processed * 3), expectant_vtable_fields);
+
+ for (uint16_t id = fields_processed; id < expectant_vtable_fields; ++id) {
+ const uint64_t field_offset = offset_start + id * sizeof(uint16_t);
+
+ const auto offset_from_table = ReadScalar<uint16_t>(field_offset);
+
+ BinaryRegionComment field_comment;
+ field_comment.type = BinaryRegionCommentType::VTableUnknownFieldOffset;
+ field_comment.index = id;
+
+ if (!offset_from_table.has_value()) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+ SetError(field_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, field_comment));
+ continue;
+ }
+
+ VTable::Entry entry;
+ entry.field = nullptr; // No field to reference.
+ entry.offset_from_table = offset_from_table.value();
+ fields.insert(std::make_pair(id, entry));
+
+ regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+ BinaryRegionType::VOffset, 0, 0,
+ field_comment));
+ }
+
+ sections_[vtable_offset] = MakeBinarySection(
+ table->name()->str(), BinarySectionType::VTable, std::move(regions));
+
+ VTable vtable;
+ vtable.fields = std::move(fields);
+ vtable.table_size = table_size;
+ vtable.vtable_size = vtable_size;
+
+ vtables_[vtable_offset] = vtable;
+}
+
+void BinaryAnnotator::BuildTable(const uint64_t table_offset,
+ const BinarySectionType type,
+ const reflection::Object *const table) {
+ if (ContainsSection(table_offset)) { return; }
+
+ BinaryRegionComment vtable_offset_comment;
+ vtable_offset_comment.type = BinaryRegionCommentType::TableVTableOffset;
+
+ const auto vtable_soffset = ReadScalar<int32_t>(table_offset);
+
+ if (!vtable_soffset.has_value()) {
+ const uint64_t remaining = RemainingBytes(table_offset);
+ SetError(vtable_offset_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "4");
+
+ AddSection(
+ table_offset,
+ MakeSingleRegionBinarySection(
+ table->name()->str(), type,
+ MakeBinaryRegion(table_offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, vtable_offset_comment)));
+
+ // If there aren't enough bytes left to read the vtable offset, there is
+ // nothing we can do.
+ return;
+ }
+
+ // Tables start with the vtable
+ const uint64_t vtable_offset = table_offset - vtable_soffset.value();
+
+ if (!IsValidOffset(vtable_offset)) {
+ SetError(vtable_offset_comment,
+ BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+
+ AddSection(table_offset,
+ MakeSingleRegionBinarySection(
+ table->name()->str(), type,
+ MakeBinaryRegion(table_offset, sizeof(int32_t),
+ BinaryRegionType::SOffset, 0, vtable_offset,
+ vtable_offset_comment)));
+
+ // There isn't much to do with an invalid vtable offset, as we won't be able
+ // to intepret the rest of the table fields.
+ return;
+ }
+
+ std::vector<BinaryRegion> regions;
+ regions.push_back(MakeBinaryRegion(table_offset, sizeof(int32_t),
+ BinaryRegionType::SOffset, 0,
+ vtable_offset, vtable_offset_comment));
+
+ // Parse the vtable first so we know what the rest of the fields in the table
+ // are.
+ BuildVTable(vtable_offset, table, table_offset);
+
+ auto vtable_entry = vtables_.find(vtable_offset);
+ if (vtable_entry == vtables_.end()) {
+ // There is no valid vtable for this table, so we cannot process the rest of
+ // the table entries.
+ return;
+ }
+
+ const VTable &vtable = vtable_entry->second;
+
+ // This is the size and length of this table.
+ const uint16_t table_size = vtable.table_size;
+ uint64_t table_end_offset = table_offset + table_size;
+
+ if (!IsValidOffset(table_end_offset - 1)) {
+ // We already validated the table size in BuildVTable, but we have to make
+ // sure we don't use a bad value here.
+ table_end_offset = binary_length_;
+ }
+
+ // We need to iterate over the vtable fields by their offset in the binary,
+ // not by their IDs. So copy them over to another vector that we can sort on
+ // the offset_from_table property.
+ std::vector<VTable::Entry> fields;
+ for (const auto &vtable_field : vtable.fields) {
+ fields.push_back(vtable_field.second);
+ }
+
+ std::stable_sort(fields.begin(), fields.end(),
+ [](const VTable::Entry &a, const VTable::Entry &b) {
+ return a.offset_from_table < b.offset_from_table;
+ });
+
+ // Iterate over all the fields by order of their offset.
+ for (size_t i = 0; i < fields.size(); ++i) {
+ const reflection::Field *field = fields[i].field;
+ const uint16_t offset_from_table = fields[i].offset_from_table;
+
+ if (offset_from_table == 0) {
+ // Skip non-present fields.
+ continue;
+ }
+
+ // The field offsets are relative to the start of the table.
+ const uint64_t field_offset = table_offset + offset_from_table;
+
+ if (!IsValidOffset(field_offset)) {
+ // The field offset is larger than the binary, nothing we can do.
+ continue;
+ }
+
+ // We have a vtable entry for a non-existant field, that means its a binary
+ // generated by a newer schema than we are currently processing.
+ if (field == nullptr) {
+ // Calculate the length of this unknown field.
+ const uint64_t unknown_field_length =
+ // Check if there is another unknown field after this one.
+ ((i + 1 < fields.size())
+ ? table_offset + fields[i + 1].offset_from_table
+ // Otherwise use the known end of the table.
+ : table_end_offset) -
+ field_offset;
+
+ if (unknown_field_length == 0) { continue; }
+
+ std::string hint;
+
+ if (unknown_field_length == 4) {
+ const auto relative_offset = ReadScalar<uint32_t>(field_offset);
+ if (relative_offset.has_value()) {
+ // The field is 4 in length, so it could be an offset? Provide a hint.
+ hint += "<possibly an offset? Check Loc: +0x";
+ hint += ToHex(field_offset + relative_offset.value());
+ hint += ">";
+ }
+ }
+
+ BinaryRegionComment unknown_field_comment;
+ unknown_field_comment.type = BinaryRegionCommentType::TableUnknownField;
+
+ if (!IsValidRead(field_offset, unknown_field_length)) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+
+ SetError(unknown_field_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(unknown_field_length));
+
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, unknown_field_comment));
+ continue;
+ }
+
+ unknown_field_comment.default_value = hint;
+
+ regions.push_back(MakeBinaryRegion(
+ field_offset, unknown_field_length, BinaryRegionType::Unknown,
+ unknown_field_length, 0, unknown_field_comment));
+ continue;
+ }
+
+ if (IsScalar(field->type()->base_type())) {
+ // These are the raw values store in the table.
+ const uint64_t type_size = GetTypeSize(field->type()->base_type());
+ const BinaryRegionType region_type =
+ GetRegionType(field->type()->base_type());
+
+ BinaryRegionComment scalar_field_comment;
+ scalar_field_comment.type = BinaryRegionCommentType::TableField;
+ scalar_field_comment.name =
+ std::string(field->name()->c_str()) + "` (" +
+ reflection::EnumNameBaseType(field->type()->base_type()) + ")";
+
+ if (!IsValidRead(field_offset, type_size)) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+ SetError(scalar_field_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(type_size));
+
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, scalar_field_comment));
+ continue;
+ }
+
+ if (IsUnionType(field)) {
+ // This is a type for a union. Validate the value
+ const auto enum_value = ReadScalar<uint8_t>(field_offset);
+
+ // This should always have a value, due to the IsValidRead check above.
+ if (!IsValidUnionValue(field, enum_value.value())) {
+ SetError(scalar_field_comment,
+ BinaryRegionStatus::ERROR_INVALID_UNION_TYPE);
+
+ regions.push_back(MakeBinaryRegion(field_offset, type_size,
+ region_type, 0, 0,
+ scalar_field_comment));
+ continue;
+ }
+ }
+
+ regions.push_back(MakeBinaryRegion(field_offset, type_size, region_type,
+ 0, 0, scalar_field_comment));
+ continue;
+ }
+
+ // Read the offset
+ 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;
+ offset_field_comment.name = field->name()->c_str();
+ const std::string offset_prefix =
+ "offset to field `" + std::string(field->name()->c_str()) + "`";
+
+ // Validate any field that isn't inline (i.e., non-structs).
+ if (!IsInlineField(field)) {
+ if (!offset_from_field.has_value()) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+
+ SetError(offset_field_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, offset_field_comment));
+ continue;
+ }
+
+ offset_of_next_item = field_offset + offset_from_field.value();
+
+ 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));
+ continue;
+ }
+ }
+
+ switch (field->type()->base_type()) {
+ case reflection::BaseType::Obj: {
+ const reflection::Object *next_object =
+ schema_->objects()->Get(field->type()->index());
+
+ if (next_object->is_struct()) {
+ // Structs are stored inline.
+ BuildStruct(field_offset, regions, next_object);
+ } 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));
+
+ BuildTable(offset_of_next_item, BinarySectionType::Table,
+ next_object);
+ }
+ } break;
+
+ 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));
+ 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));
+ BuildVector(offset_of_next_item, table, field, table_offset, vtable);
+ } break;
+
+ case reflection::BaseType::Union: {
+ const uint64_t union_offset = offset_of_next_item;
+
+ // The union type field is always one less than the union itself.
+ const uint16_t union_type_id = field->id() - 1;
+
+ auto vtable_field = vtable.fields.find(union_type_id);
+ if (vtable_field == vtable.fields.end()) {
+ // TODO(dbaileychess): need to capture this error condition.
+ break;
+ }
+ offset_field_comment.default_value = "(union)";
+
+ const uint64_t type_offset =
+ table_offset + vtable_field->second.offset_from_table;
+
+ const auto realized_type = ReadScalar<uint8_t>(type_offset);
+ if (!realized_type.has_value()) {
+ const uint64_t remaining = RemainingBytes(type_offset);
+ SetError(offset_field_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "1");
+ regions.push_back(MakeBinaryRegion(
+ type_offset, remaining, BinaryRegionType::Unknown, remaining, 0,
+ offset_field_comment));
+ continue;
+ }
+
+ if (!IsValidUnionValue(field, realized_type.value())) {
+ // We already export an error in the union type field, so just skip
+ // building the union itself and it will default to an unreference
+ // Binary section.
+ continue;
+ }
+
+ const std::string enum_type =
+ BuildUnion(union_offset, realized_type.value(), field);
+
+ offset_field_comment.default_value =
+ "(union of type `" + enum_type + "`)";
+
+ regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint32_t),
+ BinaryRegionType::UOffset, 0,
+ union_offset, offset_field_comment));
+
+ } break;
+
+ default: break;
+ }
+ }
+
+ // Handle the case where there is padding after the last known binary
+ // region. Calculate where we left off towards the expected end of the
+ // table.
+ const uint64_t i = regions.back().offset + regions.back().length + 1;
+
+ if (i < table_end_offset) {
+ const uint64_t pad_bytes = table_end_offset - i + 1;
+
+ BinaryRegionComment padding_comment;
+ padding_comment.type = BinaryRegionCommentType::Padding;
+
+ regions.push_back(MakeBinaryRegion(i - 1, pad_bytes * sizeof(uint8_t),
+ BinaryRegionType::Uint8, pad_bytes, 0,
+ padding_comment));
+ }
+
+ AddSection(table_offset,
+ MakeBinarySection(table->name()->str(), type, std::move(regions)));
+}
+
+uint64_t BinaryAnnotator::BuildStruct(const uint64_t struct_offset,
+ std::vector<BinaryRegion> ®ions,
+ const reflection::Object *const object) {
+ if (!object->is_struct()) { return struct_offset; }
+ uint64_t offset = struct_offset;
+
+ // Loop over all the fields in increasing order
+ ForAllFields(object, /*reverse=*/false, [&](const reflection::Field *field) {
+ if (IsScalar(field->type()->base_type())) {
+ // Structure Field value
+ const uint64_t type_size = GetTypeSize(field->type()->base_type());
+ const BinaryRegionType region_type =
+ GetRegionType(field->type()->base_type());
+
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::StructField;
+ comment.name =
+ std::string(object->name()->c_str()) + "." + field->name()->c_str();
+ comment.default_value = "(" +
+ std::string(reflection::EnumNameBaseType(
+ field->type()->base_type())) +
+ ")";
+
+ if (!IsValidRead(offset, type_size)) {
+ const uint64_t remaining = RemainingBytes(offset);
+ SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(type_size));
+ regions.push_back(MakeBinaryRegion(offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, comment));
+
+ // TODO(dbaileychess): Should I bail out here? This sets offset to the
+ // end of the binary. So all other reads in the loop should fail.
+ offset += remaining;
+ return;
+ }
+
+ regions.push_back(
+ MakeBinaryRegion(offset, type_size, region_type, 0, 0, comment));
+ offset += type_size;
+ } else if (field->type()->base_type() == reflection::BaseType::Obj) {
+ // Structs are stored inline, even when nested.
+ offset = BuildStruct(offset, regions,
+ schema_->objects()->Get(field->type()->index()));
+ } else if (field->type()->base_type() == reflection::BaseType::Array) {
+ const bool is_scalar = IsScalar(field->type()->element());
+ const uint64_t type_size = GetTypeSize(field->type()->element());
+ const BinaryRegionType region_type =
+ GetRegionType(field->type()->element());
+
+ // Arrays are just repeated structures.
+ for (uint16_t i = 0; i < field->type()->fixed_length(); ++i) {
+ if (is_scalar) {
+ BinaryRegionComment array_comment;
+ array_comment.type = BinaryRegionCommentType::ArrayField;
+ array_comment.name = std::string(object->name()->c_str()) + "." +
+ field->name()->c_str();
+ array_comment.index = i;
+ array_comment.default_value =
+ "(" +
+ std::string(
+ reflection::EnumNameBaseType(field->type()->element())) +
+ ")";
+
+ if (!IsValidRead(offset, type_size)) {
+ const uint64_t remaining = RemainingBytes(offset);
+
+ SetError(array_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(type_size));
+
+ regions.push_back(MakeBinaryRegion(offset, remaining,
+ BinaryRegionType::Unknown,
+ remaining, 0, array_comment));
+
+ // TODO(dbaileychess): Should I bail out here? This sets offset to
+ // the end of the binary. So all other reads in the loop should
+ // fail.
+ offset += remaining;
+ break;
+ }
+
+ regions.push_back(MakeBinaryRegion(offset, type_size, region_type, 0,
+ 0, array_comment));
+
+ offset += type_size;
+ } else {
+ // Array of Structs.
+ //
+ // TODO(dbaileychess): This works, but the comments on the fields lose
+ // some context. Need to figure a way how to plumb the nested arrays
+ // comments together that isn't too confusing.
+ offset = BuildStruct(offset, regions,
+ schema_->objects()->Get(field->type()->index()));
+ }
+ }
+ }
+
+ // Insert any padding after this field.
+ const uint16_t padding = field->padding();
+ if (padding > 0 && IsValidOffset(offset + padding)) {
+ BinaryRegionComment padding_comment;
+ padding_comment.type = BinaryRegionCommentType::Padding;
+
+ regions.push_back(MakeBinaryRegion(offset, padding,
+ BinaryRegionType::Uint8, padding, 0,
+ padding_comment));
+ offset += padding;
+ }
+ });
+
+ return offset;
+}
+
+void BinaryAnnotator::BuildString(const uint64_t string_offset,
+ const reflection::Object *const table,
+ const reflection::Field *const field) {
+ // Check if we have already generated this string section, and this is a
+ // shared string instance.
+ if (ContainsSection(string_offset)) { return; }
+
+ std::vector<BinaryRegion> regions;
+ const auto string_length = ReadScalar<uint32_t>(string_offset);
+
+ BinaryRegionComment string_length_comment;
+ string_length_comment.type = BinaryRegionCommentType::StringLength;
+
+ if (!string_length.has_value()) {
+ const uint64_t remaining = RemainingBytes(string_offset);
+
+ SetError(string_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "4");
+
+ regions.push_back(MakeBinaryRegion(string_offset, remaining,
+ BinaryRegionType::Unknown, remaining, 0,
+ string_length_comment));
+
+ } else {
+ const uint32_t string_size = string_length.value();
+ const uint64_t string_end =
+ string_offset + sizeof(uint32_t) + string_size + sizeof(char);
+
+ if (!IsValidOffset(string_end - 1)) {
+ SetError(string_length_comment,
+ BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+
+ regions.push_back(MakeBinaryRegion(string_offset, sizeof(uint32_t),
+ BinaryRegionType::Uint32, 0, 0,
+ string_length_comment));
+ } else {
+ regions.push_back(MakeBinaryRegion(string_offset, sizeof(uint32_t),
+ BinaryRegionType::Uint32, 0, 0,
+ string_length_comment));
+
+ BinaryRegionComment string_comment;
+ string_comment.type = BinaryRegionCommentType::StringValue;
+
+ regions.push_back(MakeBinaryRegion(string_offset + sizeof(uint32_t),
+ string_size, BinaryRegionType::Char,
+ string_size, 0, string_comment));
+
+ BinaryRegionComment string_terminator_comment;
+ string_terminator_comment.type =
+ BinaryRegionCommentType::StringTerminator;
+
+ regions.push_back(MakeBinaryRegion(
+ string_offset + sizeof(uint32_t) + string_size, sizeof(char),
+ BinaryRegionType::Char, 0, 0, string_terminator_comment));
+ }
+ }
+
+ AddSection(string_offset,
+ MakeBinarySection(std::string(table->name()->c_str()) + "." +
+ field->name()->c_str(),
+ BinarySectionType::String, std::move(regions)));
+}
+
+void BinaryAnnotator::BuildVector(const uint64_t vector_offset,
+ const reflection::Object *const table,
+ const reflection::Field *const field,
+ const uint64_t parent_table_offset,
+ const VTable &vtable) {
+ if (ContainsSection(vector_offset)) { return; }
+
+ BinaryRegionComment vector_length_comment;
+ vector_length_comment.type = BinaryRegionCommentType::VectorLength;
+
+ const auto vector_length = ReadScalar<uint32_t>(vector_offset);
+ if (!vector_length.has_value()) {
+ const uint64_t remaining = RemainingBytes(vector_offset);
+ SetError(vector_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "4");
+
+ AddSection(
+ vector_offset,
+ MakeSingleRegionBinarySection(
+ std::string(table->name()->c_str()) + "." + field->name()->c_str(),
+ BinarySectionType::Vector,
+ MakeBinaryRegion(vector_offset, remaining,
+ BinaryRegionType::Unknown, remaining, 0,
+ vector_length_comment)));
+ return;
+ }
+
+ // 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_length.value() * GetElementSize(field);
+
+ if (!IsValidOffset(last_item_offset - 1)) {
+ SetError(vector_length_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+ AddSection(
+ vector_offset,
+ 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)));
+
+ return;
+ }
+
+ std::vector<BinaryRegion> regions;
+
+ regions.push_back(MakeBinaryRegion(vector_offset, sizeof(uint32_t),
+ BinaryRegionType::Uint32, 0, 0,
+ vector_length_comment));
+
+ uint64_t offset = vector_offset + sizeof(uint32_t);
+
+ switch (field->type()->element()) {
+ case reflection::BaseType::Obj: {
+ const reflection::Object *object =
+ schema_->objects()->Get(field->type()->index());
+
+ if (object->is_struct()) {
+ // Vector of structs
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ // Structs are inline to the vector.
+ const uint64_t next_offset = BuildStruct(offset, regions, object);
+ if (next_offset == offset) { break; }
+ offset = next_offset;
+ }
+ } else {
+ // Vector of objects
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ BinaryRegionComment vector_object_comment;
+ vector_object_comment.type =
+ BinaryRegionCommentType::VectorTableValue;
+ vector_object_comment.index = i;
+
+ const auto table_relative_offset = ReadScalar<uint32_t>(offset);
+ if (!table_relative_offset.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+ regions.push_back(
+ MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, vector_object_comment));
+ break;
+ }
+
+ // The table offset is relative from the offset location itself.
+ const uint64_t table_offset = offset + table_relative_offset.value();
+
+ if (!IsValidOffset(table_offset)) {
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ table_offset, vector_object_comment));
+
+ offset += sizeof(uint32_t);
+ continue;
+ }
+
+ if (table_offset == parent_table_offset) {
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_CYCLE_DETECTED);
+ // A cycle detected where a table vector field is pointing to
+ // itself. This should only happen in corrupted files.
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ table_offset, vector_object_comment));
+
+ offset += sizeof(uint32_t);
+ continue;
+ }
+
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ table_offset, vector_object_comment));
+
+ offset += sizeof(uint32_t);
+
+ BuildTable(table_offset, BinarySectionType::Table, object);
+ }
+ }
+ } break;
+ case reflection::BaseType::String: {
+ // Vector of strings
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ BinaryRegionComment vector_object_comment;
+ vector_object_comment.type = BinaryRegionCommentType::VectorStringValue;
+ vector_object_comment.index = i;
+
+ const auto string_relative_offset = ReadScalar<uint32_t>(offset);
+ if (!string_relative_offset.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+ regions.push_back(
+ MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, vector_object_comment));
+ break;
+ }
+
+ // The string offset is relative from the offset location itself.
+ const uint64_t string_offset = offset + string_relative_offset.value();
+
+ if (!IsValidOffset(string_offset)) {
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ string_offset, vector_object_comment));
+
+ offset += sizeof(uint32_t);
+ continue;
+ }
+
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ string_offset, vector_object_comment));
+
+ BuildString(string_offset, table, field);
+
+ offset += sizeof(uint32_t);
+ }
+ } break;
+ case reflection::BaseType::Union: {
+ // Vector of unions
+ // Unions have both their realized type (uint8_t for now) that are
+ // stored separately. These are stored in the field->index() - 1
+ // location.
+ const uint16_t union_type_vector_id = field->id() - 1;
+
+ auto vtable_entry = vtable.fields.find(union_type_vector_id);
+ if (vtable_entry == vtable.fields.end()) {
+ // TODO(dbaileychess): need to capture this error condition.
+ break;
+ }
+
+ const uint64_t union_type_vector_field_offset =
+ parent_table_offset + vtable_entry->second.offset_from_table;
+
+ const auto union_type_vector_field_relative_offset =
+ ReadScalar<uint16_t>(union_type_vector_field_offset);
+
+ if (!union_type_vector_field_relative_offset.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+ BinaryRegionComment vector_union_comment;
+ vector_union_comment.type = BinaryRegionCommentType::VectorUnionValue;
+ SetError(vector_union_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
+
+ regions.push_back(MakeBinaryRegion(offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, vector_union_comment));
+
+ break;
+ }
+
+ // Get the offset to the first type (the + sizeof(uint32_t) is to skip
+ // over the vector length which we already know). Validation happens
+ // within the loop below.
+ const uint64_t union_type_vector_data_offset =
+ union_type_vector_field_offset +
+ union_type_vector_field_relative_offset.value() + sizeof(uint32_t);
+
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::VectorUnionValue;
+ comment.index = i;
+
+ const auto union_relative_offset = ReadScalar<uint32_t>(offset);
+ if (!union_relative_offset.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+
+ SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+ regions.push_back(MakeBinaryRegion(offset, remaining,
+ BinaryRegionType::Unknown,
+ remaining, 0, comment));
+
+ break;
+ }
+
+ // The union offset is relative from the offset location itself.
+ const uint64_t union_offset = offset + union_relative_offset.value();
+
+ if (!IsValidOffset(union_offset)) {
+ SetError(comment, BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+
+ regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
+ BinaryRegionType::UOffset, 0,
+ union_offset, comment));
+ continue;
+ }
+
+ const auto realized_type =
+ ReadScalar<uint8_t>(union_type_vector_data_offset + i);
+
+ if (!realized_type.has_value()) {
+ SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "1");
+ regions.push_back(MakeBinaryRegion(
+ offset, 0, BinaryRegionType::Unknown, 0, 0, comment));
+ continue;
+ }
+
+ if (!IsValidUnionValue(vtable_entry->second.field->type()->index(),
+ realized_type.value())) {
+ // We already export an error in the union type field, so just skip
+ // building the union itself and it will default to an unreference
+ // Binary section.
+ offset += sizeof(uint32_t);
+ continue;
+ }
+
+ const std::string enum_type =
+ BuildUnion(union_offset, realized_type.value(), field);
+
+ comment.default_value = "(`" + enum_type + "`)";
+ regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
+ BinaryRegionType::UOffset, 0,
+ union_offset, comment));
+
+ offset += sizeof(uint32_t);
+ }
+ } break;
+ default: {
+ if (IsScalar(field->type()->element())) {
+ const BinaryRegionType binary_region_type =
+ GetRegionType(field->type()->element());
+
+ const uint64_t type_size = GetTypeSize(field->type()->element());
+
+ // TODO(dbaileychess): It might be nicer to user the
+ // BinaryRegion.array_length field to indicate this.
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ BinaryRegionComment vector_scalar_comment;
+ vector_scalar_comment.type = BinaryRegionCommentType::VectorValue;
+ vector_scalar_comment.index = i;
+
+ if (!IsValidRead(offset, type_size)) {
+ const uint64_t remaining = RemainingBytes(offset);
+
+ SetError(vector_scalar_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(type_size));
+
+ regions.push_back(
+ MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, vector_scalar_comment));
+ break;
+ }
+
+ if (IsUnionType(field->type()->element())) {
+ // This is a type for a union. Validate the value
+ const auto enum_value = ReadScalar<uint8_t>(offset);
+
+ // This should always have a value, due to the IsValidRead check
+ // above.
+ if (!IsValidUnionValue(field->type()->index(),
+ enum_value.value())) {
+ SetError(vector_scalar_comment,
+ BinaryRegionStatus::ERROR_INVALID_UNION_TYPE);
+ regions.push_back(MakeBinaryRegion(offset, type_size,
+ binary_region_type, 0, 0,
+ vector_scalar_comment));
+ offset += type_size;
+ continue;
+ }
+ }
+
+ regions.push_back(MakeBinaryRegion(offset, type_size,
+ binary_region_type, 0, 0,
+ vector_scalar_comment));
+ offset += type_size;
+ }
+ }
+ } break;
+ }
+ AddSection(vector_offset,
+ MakeBinarySection(std::string(table->name()->c_str()) + "." +
+ field->name()->c_str(),
+ BinarySectionType::Vector, std::move(regions)));
+}
+
+std::string BinaryAnnotator::BuildUnion(const uint64_t union_offset,
+ const uint8_t realized_type,
+ const reflection::Field *const field) {
+ const reflection::Enum *next_enum =
+ schema_->enums()->Get(field->type()->index());
+
+ const reflection::EnumVal *enum_val = next_enum->values()->Get(realized_type);
+
+ if (ContainsSection(union_offset)) { return enum_val->name()->c_str(); }
+
+ const reflection::Type *union_type = enum_val->union_type();
+
+ if (union_type->base_type() == reflection::BaseType::Obj) {
+ const reflection::Object *object =
+ schema_->objects()->Get(union_type->index());
+
+ if (object->is_struct()) {
+ // Union of vectors point to a new Binary section
+ std::vector<BinaryRegion> regions;
+
+ BuildStruct(union_offset, regions, object);
+
+ AddSection(
+ union_offset,
+ MakeBinarySection(std::string(object->name()->c_str()) + "." +
+ field->name()->c_str(),
+ BinarySectionType::Union, std::move(regions)));
+ } else {
+ BuildTable(union_offset, BinarySectionType::Table, object);
+ }
+ }
+ // TODO(dbaileychess): handle the other union types.
+
+ return enum_val->name()->c_str();
+}
+
+void BinaryAnnotator::FixMissingRegions() {
+ std::vector<BinaryRegion> regions_to_insert;
+ for (auto ¤t_section : sections_) {
+ BinarySection §ion = current_section.second;
+ if (section.regions.empty()) {
+ // TODO(dbaileychess): is this possible?
+ continue;
+ }
+
+ uint64_t offset = section.regions[0].offset + section.regions[0].length;
+ for (size_t i = 1; i < section.regions.size(); ++i) {
+ BinaryRegion ®ion = section.regions[i];
+
+ const uint64_t next_offset = region.offset;
+ if (!IsValidOffset(next_offset)) {
+ // TODO(dbaileychess): figure out how we get into this situation.
+ continue;
+ }
+
+ if (offset < next_offset) {
+ const uint64_t padding_bytes = next_offset - offset;
+
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::Padding;
+
+ if (IsNonZeroRegion(offset, padding_bytes, binary_)) {
+ SetError(comment, BinaryRegionStatus::WARN_NO_REFERENCES);
+ regions_to_insert.push_back(
+ MakeBinaryRegion(offset, padding_bytes, BinaryRegionType::Unknown,
+ padding_bytes, 0, comment));
+ } else {
+ regions_to_insert.push_back(
+ MakeBinaryRegion(offset, padding_bytes, BinaryRegionType::Uint8,
+ padding_bytes, 0, comment));
+ }
+ }
+ offset = next_offset + region.length;
+ }
+
+ if (!regions_to_insert.empty()) {
+ section.regions.insert(section.regions.end(), regions_to_insert.begin(),
+ regions_to_insert.end());
+ std::stable_sort(section.regions.begin(), section.regions.end(),
+ BinaryRegionSort);
+ regions_to_insert.clear();
+ }
+ }
+}
+
+void BinaryAnnotator::FixMissingSections() {
+ uint64_t offset = 0;
+
+ std::vector<BinarySection> sections_to_insert;
+
+ for (auto ¤t_section : sections_) {
+ BinarySection §ion = current_section.second;
+ const uint64_t section_start_offset = current_section.first;
+ const uint64_t section_end_offset =
+ section.regions.back().offset + section.regions.back().length;
+
+ if (offset < section_start_offset) {
+ // We are at an offset that is less then the current section.
+ const uint64_t pad_bytes = section_start_offset - offset + 1;
+
+ sections_to_insert.push_back(
+ GenerateMissingSection(offset - 1, pad_bytes, binary_));
+ }
+ offset = section_end_offset + 1;
+ }
+
+ // Handle the case where there are still bytes left in the binary that are
+ // unaccounted for.
+ if (offset < binary_length_) {
+ const uint64_t pad_bytes = binary_length_ - offset + 1;
+ sections_to_insert.push_back(
+ GenerateMissingSection(offset - 1, pad_bytes, binary_));
+ }
+
+ for (const BinarySection §ion_to_insert : sections_to_insert) {
+ AddSection(section_to_insert.regions[0].offset, section_to_insert);
+ }
+}
+
+bool BinaryAnnotator::ContainsSection(const uint64_t offset) {
+ auto it = sections_.lower_bound(offset);
+ // If the section is found, check that it is exactly equal its offset.
+ if (it != sections_.end() && it->first == offset) { return true; }
+
+ // If this was the first section, there are no other previous sections to
+ // check.
+ if (it == sections_.begin()) { return false; }
+
+ // Go back one section.
+ --it;
+
+ // And check that if the offset is covered by the section.
+ return offset >= it->first && offset < it->second.regions.back().offset +
+ it->second.regions.back().length;
+}
+
+} // namespace flatbuffers
\ No newline at end of file
diff --git a/third_party/flatbuffers/src/binary_annotator.h b/third_party/flatbuffers/src/binary_annotator.h
new file mode 100644
index 0000000..23e4198
--- /dev/null
+++ b/third_party/flatbuffers/src/binary_annotator.h
@@ -0,0 +1,392 @@
+/*
+ * Copyright 2021 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_BINARY_ANNOTATOR_H_
+#define FLATBUFFERS_BINARY_ANNOTATOR_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/reflection.h"
+#include "flatbuffers/stl_emulation.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+enum class BinaryRegionType {
+ Unknown = 0,
+ UOffset = 1,
+ SOffset = 2,
+ VOffset = 3,
+ Bool = 4,
+ Byte = 5,
+ Char = 6,
+ Uint8 = 7,
+ Int8 = 8,
+ Uint16 = 9,
+ Int16 = 10,
+ Uint32 = 11,
+ Int32 = 12,
+ Uint64 = 13,
+ Int64 = 14,
+ Float = 15,
+ Double = 16,
+ UType = 17,
+};
+
+template<typename T>
+static inline std::string ToHex(T i, size_t width = sizeof(T)) {
+ std::stringstream stream;
+ stream << std::hex << std::uppercase << std::setfill('0') << std::setw(width)
+ << i;
+ return stream.str();
+}
+
+// Specialized version for uint8_t that don't work well with std::hex.
+static inline std::string ToHex(uint8_t i) {
+ return ToHex(static_cast<int>(i), 2);
+}
+
+enum class BinaryRegionStatus {
+ OK = 0,
+ WARN = 100,
+ WARN_NO_REFERENCES,
+ WARN_CORRUPTED_PADDING,
+ WARN_PADDING_LENGTH,
+ ERROR = 200,
+ // An offset is pointing outside the binary bounds.
+ ERROR_OFFSET_OUT_OF_BINARY,
+ // Expecting to read N bytes but not enough remain in the binary.
+ ERROR_INCOMPLETE_BINARY,
+ // When a length of a vtable/vector is longer than possible.
+ ERROR_LENGTH_TOO_LONG,
+ // When a length of a vtable/vector is shorter than possible.
+ ERROR_LENGTH_TOO_SHORT,
+ // A field mark required is not present in the vtable.
+ ERROR_REQUIRED_FIELD_NOT_PRESENT,
+ // A realized union type is not within the enum bounds.
+ ERROR_INVALID_UNION_TYPE,
+ // Occurs when there is a cycle in offsets.
+ ERROR_CYCLE_DETECTED,
+};
+
+enum class BinaryRegionCommentType {
+ Unknown = 0,
+ SizePrefix,
+ // The offset to the root table.
+ RootTableOffset,
+ // The optional 4-char file identifier.
+ FileIdentifier,
+ // Generic 0-filled padding
+ Padding,
+ // The size of the vtable.
+ VTableSize,
+ // The size of the referring table.
+ VTableRefferingTableLength,
+ // Offsets to vtable fields.
+ VTableFieldOffset,
+ // Offsets to unknown vtable fields.
+ VTableUnknownFieldOffset,
+ // The vtable offset of a table.
+ TableVTableOffset,
+ // A "inline" table field value.
+ TableField,
+ // A table field that is unknown.
+ TableUnknownField,
+ // A table field value that points to another section.
+ TableOffsetField,
+ // A struct field value.
+ StructField,
+ // A array field value.
+ ArrayField,
+ // The length of the string.
+ StringLength,
+ // The string contents.
+ StringValue,
+ // The explicit string terminator.
+ StringTerminator,
+ // The length of the vector (# of items).
+ VectorLength,
+ // A "inline" value of a vector.
+ VectorValue,
+ // A vector value that points to another section.
+ VectorTableValue,
+ VectorStringValue,
+ VectorUnionValue,
+};
+
+struct BinaryRegionComment {
+ BinaryRegionStatus status = BinaryRegionStatus::OK;
+
+ // If status is non OK, this may be filled in with additional details.
+ std::string status_message;
+
+ BinaryRegionCommentType type = BinaryRegionCommentType::Unknown;
+
+ std::string name;
+
+ std::string default_value;
+
+ size_t index = 0;
+};
+
+struct BinaryRegion {
+ // Offset into the binary where this region begins.
+ uint64_t offset = 0;
+
+ // The length of this region in bytes.
+ uint64_t length = 0;
+
+ // The underlying datatype of this region
+ BinaryRegionType type = BinaryRegionType::Unknown;
+
+ // If `type` is an array/vector, this is the number of those types this region
+ // encompasses.
+ uint64_t array_length = 0;
+
+ // If the is an offset to some other region, this is what it points to. The
+ // offset is relative to overall binary, not to this region.
+ uint64_t points_to_offset = 0;
+
+ // The comment on the region.
+ BinaryRegionComment comment;
+};
+
+enum class BinarySectionType {
+ Unknown = 0,
+ Header = 1,
+ Table = 2,
+ RootTable = 3,
+ VTable = 4,
+ Struct = 5,
+ String = 6,
+ Vector = 7,
+ Union = 8,
+ Padding = 9,
+};
+
+// A section of the binary that is grouped together in some logical manner, and
+// often is pointed too by some other offset BinaryRegion. Sections include
+// `tables`, `vtables`, `strings`, `vectors`, etc..
+struct BinarySection {
+ // User-specified name of the section, if applicable.
+ std::string name;
+
+ // The type of this section.
+ BinarySectionType type = BinarySectionType::Unknown;
+
+ // The binary regions that make up this section, in order of their offsets.
+ std::vector<BinaryRegion> regions;
+};
+
+inline static BinaryRegionType GetRegionType(reflection::BaseType base_type) {
+ switch (base_type) {
+ case reflection::BaseType::UType: return BinaryRegionType::UType;
+ case reflection::BaseType::Bool: return BinaryRegionType::Uint8;
+ case reflection::BaseType::Byte: return BinaryRegionType::Uint8;
+ case reflection::BaseType::UByte: return BinaryRegionType::Uint8;
+ case reflection::BaseType::Short: return BinaryRegionType::Int16;
+ case reflection::BaseType::UShort: return BinaryRegionType::Uint16;
+ case reflection::BaseType::Int: return BinaryRegionType::Uint32;
+ case reflection::BaseType::UInt: return BinaryRegionType::Uint32;
+ case reflection::BaseType::Long: return BinaryRegionType::Int64;
+ case reflection::BaseType::ULong: return BinaryRegionType::Uint64;
+ case reflection::BaseType::Float: return BinaryRegionType::Float;
+ case reflection::BaseType::Double: return BinaryRegionType::Double;
+ default: return BinaryRegionType::Unknown;
+ }
+}
+
+inline static std::string ToString(const BinaryRegionType type) {
+ switch (type) {
+ case BinaryRegionType::UOffset: return "UOffset32";
+ case BinaryRegionType::SOffset: return "SOffset32";
+ case BinaryRegionType::VOffset: return "VOffset16";
+ case BinaryRegionType::Bool: return "bool";
+ case BinaryRegionType::Char: return "char";
+ case BinaryRegionType::Byte: return "int8_t";
+ case BinaryRegionType::Uint8: return "uint8_t";
+ case BinaryRegionType::Uint16: return "uint16_t";
+ case BinaryRegionType::Uint32: return "uint32_t";
+ case BinaryRegionType::Uint64: return "uint64_t"; ;
+ case BinaryRegionType::Int8: return "int8_t";
+ case BinaryRegionType::Int16: return "int16_t";
+ case BinaryRegionType::Int32: return "int32_t";
+ case BinaryRegionType::Int64: return "int64_t";
+ case BinaryRegionType::Double: return "double";
+ case BinaryRegionType::Float: return "float";
+ case BinaryRegionType::UType: return "UType8";
+ case BinaryRegionType::Unknown: return "?uint8_t";
+ default: return "todo";
+ }
+}
+
+class BinaryAnnotator {
+ public:
+ explicit BinaryAnnotator(const uint8_t *const bfbs,
+ const uint64_t bfbs_length,
+ const uint8_t *const binary,
+ const uint64_t binary_length)
+ : bfbs_(bfbs),
+ bfbs_length_(bfbs_length),
+ schema_(reflection::GetSchema(bfbs)),
+ binary_(binary),
+ binary_length_(binary_length) {}
+
+ std::map<uint64_t, BinarySection> Annotate();
+
+ private:
+ struct VTable {
+ struct Entry {
+ const reflection::Field *field = nullptr;
+ uint16_t offset_from_table = 0;
+ };
+
+ // Field ID -> {field def, offset from table}
+ std::map<uint16_t, Entry> fields;
+
+ uint16_t vtable_size = 0;
+ uint16_t table_size = 0;
+ };
+
+ uint64_t BuildHeader(uint64_t offset);
+
+ void BuildVTable(uint64_t offset, const reflection::Object *table,
+ uint64_t offset_of_referring_table);
+
+ void BuildTable(uint64_t offset, const BinarySectionType type,
+ const reflection::Object *table);
+
+ uint64_t BuildStruct(uint64_t offset, std::vector<BinaryRegion> ®ions,
+ const reflection::Object *structure);
+
+ void BuildString(uint64_t offset, const reflection::Object *table,
+ const reflection::Field *field);
+
+ void BuildVector(uint64_t offset, const reflection::Object *table,
+ const reflection::Field *field, uint64_t parent_table_offset,
+ const VTable &vtable);
+
+ std::string BuildUnion(uint64_t offset, uint8_t realized_type,
+ const reflection::Field *field);
+
+ void FixMissingRegions();
+ void FixMissingSections();
+
+ inline bool IsValidOffset(const uint64_t offset) const {
+ return offset < binary_length_;
+ }
+
+ // Determines if performing a GetScalar request for `T` at `offset` would read
+ // passed the end of the binary.
+ template<typename T> inline bool IsValidRead(const uint64_t offset) const {
+ return IsValidRead(offset, sizeof(T));
+ }
+
+ inline bool IsValidRead(const uint64_t offset, const uint64_t length) const {
+ return length < binary_length_ && IsValidOffset(offset + length - 1);
+ }
+
+ // Calculate the number of bytes remaining from the given offset. If offset is
+ // > binary_length, 0 is returned.
+ uint64_t RemainingBytes(const uint64_t offset) const {
+ return IsValidOffset(offset) ? binary_length_ - offset : 0;
+ }
+
+ template<typename T>
+ flatbuffers::Optional<T> ReadScalar(const uint64_t offset) const {
+ if (!IsValidRead<T>(offset)) { return flatbuffers::nullopt; }
+
+ return flatbuffers::ReadScalar<T>(binary_ + offset);
+ }
+
+ // Adds the provided `section` keyed by the `offset` it occurs at. If a
+ // section is already added at that offset, it doesn't replace the exisiting
+ // one.
+ void AddSection(const uint64_t offset, const BinarySection §ion) {
+ sections_.insert(std::make_pair(offset, section));
+ }
+
+ bool IsInlineField(const reflection::Field *const field) {
+ if (field->type()->base_type() == reflection::BaseType::Obj) {
+ return schema_->objects()->Get(field->type()->index())->is_struct();
+ }
+ return IsScalar(field->type()->base_type());
+ }
+
+ bool IsUnionType(const reflection::BaseType type) {
+ return (type == reflection::BaseType::UType ||
+ type == reflection::BaseType::Union);
+ }
+
+ bool IsUnionType(const reflection::Field *const field) {
+ return IsUnionType(field->type()->base_type()) &&
+ field->type()->index() >= 0;
+ }
+
+ bool IsValidUnionValue(const reflection::Field *const field,
+ const uint8_t value) {
+ return IsUnionType(field) &&
+ IsValidUnionValue(field->type()->index(), value);
+ }
+
+ bool IsValidUnionValue(const uint32_t enum_id, const uint8_t value) {
+ if (enum_id >= schema_->enums()->size()) { return false; }
+
+ const reflection::Enum *enum_def = schema_->enums()->Get(enum_id);
+
+ if (enum_def == nullptr) { return false; }
+
+ return value < enum_def->values()->size();
+ }
+
+ uint64_t GetElementSize(const reflection::Field *const field) {
+ if (IsScalar(field->type()->element())) {
+ return GetTypeSize(field->type()->element());
+ }
+
+ switch (field->type()->element()) {
+ case reflection::BaseType::Obj: {
+ auto obj = schema_->objects()->Get(field->type()->index());
+ return obj->is_struct() ? obj->bytesize() : sizeof(uint32_t);
+ }
+ default: return sizeof(uint32_t);
+ }
+ }
+
+ bool ContainsSection(const uint64_t offset);
+
+ // The schema for the binary file
+ const uint8_t *bfbs_;
+ const uint64_t bfbs_length_;
+ const reflection::Schema *schema_;
+
+ // The binary data itself.
+ const uint8_t *binary_;
+ const uint64_t binary_length_;
+
+ // Map of binary offset to vtables, to dedupe vtables.
+ std::map<uint64_t, VTable> vtables_;
+
+ // The annotated binary sections, index by their absolute offset.
+ std::map<uint64_t, BinarySection> sections_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BINARY_ANNOTATOR_H_
diff --git a/third_party/flatbuffers/src/code_generators.cpp b/third_party/flatbuffers/src/code_generators.cpp
index e449a1d..f3e50c7 100644
--- a/third_party/flatbuffers/src/code_generators.cpp
+++ b/third_party/flatbuffers/src/code_generators.cpp
@@ -30,6 +30,52 @@
namespace flatbuffers {
+namespace {
+
+static 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";
+ std::string make_rule;
+
+ for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end();
+ ++it) {
+ auto &enum_def = **it;
+ if (!make_rule.empty()) make_rule += " ";
+ std::string directory =
+ BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace);
+ make_rule += directory + enum_def.name + file_extension;
+ }
+
+ for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
+ ++it) {
+ auto &struct_def = **it;
+ if (!make_rule.empty()) make_rule += " ";
+ std::string directory = BaseGenerator::NamespaceDir(
+ parser, path, *struct_def.defined_namespace);
+ make_rule += directory + struct_def.name + file_extension;
+ }
+
+ make_rule += ": ";
+ auto included_files = parser.GetIncludedFilesRecursive(file_name);
+ for (auto it = included_files.begin(); it != included_files.end(); ++it) {
+ make_rule += " " + *it;
+ }
+ 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_);
@@ -137,8 +183,9 @@
}
std::string BaseGenerator::WrapInNameSpace(const Definition &def,
+ const std::string &suffix,
bool js_ts) const {
- return WrapInNameSpace(def.defined_namespace, def.name, js_ts);
+ return WrapInNameSpace(def.defined_namespace, def.name + suffix, js_ts);
}
std::string BaseGenerator::GetNameSpace(const Definition &def) const {
@@ -305,37 +352,6 @@
return this->NaN(static_cast<double>(v));
}
-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";
- std::string make_rule;
-
- for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end();
- ++it) {
- auto &enum_def = **it;
- if (!make_rule.empty()) make_rule += " ";
- std::string directory =
- BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace);
- make_rule += directory + enum_def.name + file_extension;
- }
-
- for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
- ++it) {
- auto &struct_def = **it;
- if (!make_rule.empty()) make_rule += " ";
- std::string directory = BaseGenerator::NamespaceDir(
- parser, path, *struct_def.defined_namespace);
- make_rule += directory + struct_def.name + file_extension;
- }
-
- make_rule += ": ";
- auto included_files = parser.GetIncludedFilesRecursive(file_name);
- for (auto it = included_files.begin(); it != included_files.end(); ++it) {
- make_rule += " " + *it;
- }
- return make_rule;
-}
std::string JavaMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
@@ -346,12 +362,6 @@
return JavaCSharpMakeRule(false, parser, path, file_name);
}
-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;
-}
-
bool GenerateBinary(const Parser &parser, const std::string &path,
const std::string &file_name) {
if (parser.opts.use_flexbuffers) {
diff --git a/third_party/flatbuffers/src/flatc.cpp b/third_party/flatbuffers/src/flatc.cpp
index 3b2ef9f..1d12a17 100644
--- a/third_party/flatbuffers/src/flatc.cpp
+++ b/third_party/flatbuffers/src/flatc.cpp
@@ -19,11 +19,13 @@
#include <list>
#include <sstream>
+#include "annotated_binary_text_gen.h"
+#include "binary_annotator.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
-const char *FLATC_VERSION() { return FLATBUFFERS_VERSION(); }
+static const char *FLATC_VERSION() { return FLATBUFFERS_VERSION(); }
void FlatCompiler::ParseFile(
flatbuffers::Parser &parser, const std::string &filename,
@@ -84,6 +86,8 @@
{ "", "scoped-enums", "",
"Use C++11 style scoped and strongly typed enums. Also implies "
"--no-prefix." },
+ { "", "swift-implementation-only", "",
+ "Adds a @_implementationOnly to swift imports" },
{ "", "gen-inclues", "",
"(deprecated), this is the default behavior. If the original behavior is "
"required (no include statements) use --no-includes." },
@@ -203,7 +207,7 @@
"Used with \"binary\" and \"json\" options, it generates data using "
"schema-less FlexBuffers." },
{ "", "no-warnings", "", "Inhibit all warnings messages." },
- { "", "warning-as-errors", "", "Treat all warnings as errors." },
+ { "", "warnings-as-errors", "", "Treat all warnings as errors." },
{ "", "cs-global-alias", "",
"Prepend \"global::\" to all user generated csharp classes and "
"structs." },
@@ -215,6 +219,11 @@
"in JSON, which is unsafe unless checked by a verifier afterwards." },
{ "", "ts-flat-files", "",
"Only generated one typescript file per .fbs file." },
+ { "", "annotate", "SCHEMA",
+ "Annotate the provided BINARY_FILE with the specified SCHEMA file." },
+ { "", "no-leak-private-annotation", "",
+ "Prevents multiple type of annotations within a Fbs SCHEMA file."
+ "Currently this is required to generate private types in Rust" },
};
static void AppendTextWrappedString(std::stringstream &ss, std::string &text,
@@ -297,7 +306,7 @@
ss << ", ";
}
ss.seekp(-2, ss.cur);
- ss << "]... FILE... [-- FILE...]";
+ ss << "]... FILE... [-- BINARY_FILE...]";
std::string help = ss.str();
std::stringstream ss_textwrap;
AppendTextWrappedString(ss_textwrap, help, 80, 0);
@@ -306,7 +315,8 @@
std::string FlatCompiler::GetUsageString(const char *program_name) const {
std::stringstream ss;
- ss << "Usage: " << program_name << " [OPTION]... FILE... [-- FILE...]\n";
+ ss << "Usage: " << program_name
+ << " [OPTION]... FILE... [-- BINARY_FILE...]\n";
for (size_t i = 0; i < params_.num_generators; ++i) {
const Generator &g = params_.generators[i];
AppendOption(ss, g.option, 80, 25);
@@ -320,16 +330,48 @@
std::string files_description =
"FILEs may be schemas (must end in .fbs), binary schemas (must end in "
- ".bfbs) or JSON files (conforming to preceding schema). FILEs after the "
- "-- must be binary flatbuffer format files. Output files are named using "
- "the base file name of the input, and written to the current directory "
- "or the path given by -o. example: " +
+ ".bfbs) or JSON files (conforming to preceding schema). BINARY_FILEs "
+ "after the -- must be binary flatbuffer format files. Output files are "
+ "named using the base file name of the input, and written to the current "
+ "directory or the path given by -o. example: " +
std::string(program_name) + " -c -b schema1.fbs schema2.fbs data.json";
AppendTextWrappedString(ss, files_description, 80, 0);
ss << "\n";
return ss.str();
}
+void FlatCompiler::AnnotateBinaries(
+ const uint8_t *binary_schema, const uint64_t binary_schema_size,
+ const std::string &schema_filename,
+ const std::vector<std::string> &binary_files) {
+ for (const std::string &filename : binary_files) {
+ std::string binary_contents;
+ if (!flatbuffers::LoadFile(filename.c_str(), true, &binary_contents)) {
+ Warn("unable to load binary file: " + filename);
+ continue;
+ }
+
+ const uint8_t *binary =
+ reinterpret_cast<const uint8_t *>(binary_contents.c_str());
+ const size_t binary_size = binary_contents.size();
+
+ flatbuffers::BinaryAnnotator binary_annotator(
+ binary_schema, binary_schema_size, binary, binary_size);
+
+ auto annotations = binary_annotator.Annotate();
+
+ // TODO(dbaileychess): Right now we just support a single text-based
+ // output of the annotated binary schema, which we generate here. We
+ // could output the raw annotations instead and have third-party tools
+ // use them to generate their own output.
+ flatbuffers::AnnotatedBinaryTextGenerator text_generator(
+ flatbuffers::AnnotatedBinaryTextGenerator::Options{}, annotations,
+ binary, binary_size);
+
+ text_generator.Generate(filename, schema_filename);
+ }
+}
+
int FlatCompiler::Compile(int argc, const char **argv) {
if (params_.generators == nullptr || params_.num_generators == 0) {
return 0;
@@ -353,6 +395,7 @@
std::vector<bool> generator_enabled(params_.num_generators, false);
size_t binary_files_from = std::numeric_limits<size_t>::max();
std::string conform_to_schema;
+ std::string annotate_schema;
const char *program_name = argv[0];
@@ -390,7 +433,7 @@
opts.include_prefix = flatbuffers::ConCatPathFileName(
flatbuffers::PosixPath(argv[argi]), "");
} else if (arg == "--keep-prefix") {
- opts.keep_include_path = true;
+ opts.keep_prefix = true;
} else if (arg == "--strict-json") {
opts.strict_json = true;
} else if (arg == "--allow-non-utf8") {
@@ -452,6 +495,8 @@
opts.java_checkerframework = true;
} else if (arg == "--gen-generated") {
opts.gen_generated = true;
+ } else if (arg == "--swift-implementation-only") {
+ opts.swift_implementation_only = true;
} else if (arg == "--gen-json-emit") {
opts.gen_json_coders = true;
} else if (arg == "--object-prefix") {
@@ -554,6 +599,11 @@
opts.json_nested_legacy_flatbuffers = true;
} else if (arg == "--ts-flat-files") {
opts.ts_flat_file = true;
+ } else if (arg == "--no-leak-private-annotation") {
+ opts.no_leak_private_annotations = true;
+ } else if (arg == "--annotate") {
+ if (++argi >= argc) Error("missing path following: " + arg, true);
+ annotate_schema = flatbuffers::PosixPath(argv[argi]);
} else {
for (size_t i = 0; i < params_.num_generators; ++i) {
if (arg == "--" + params_.generators[i].option.long_opt ||
@@ -582,7 +632,8 @@
if (opts.proto_mode) {
if (any_generator)
Error("cannot generate code directly from .proto files", true);
- } else if (!any_generator && conform_to_schema.empty()) {
+ } else if (!any_generator && conform_to_schema.empty() &&
+ annotate_schema.empty()) {
Error("no options: specify at least one generator.", true);
}
@@ -592,10 +643,6 @@
"well.");
}
- if (opts.ts_flat_file && opts.generate_all) {
- Error("Combining --ts-flat-file and --gen-all is not supported.");
- }
-
flatbuffers::Parser conform_parser;
if (!conform_to_schema.empty()) {
std::string contents;
@@ -611,6 +658,53 @@
}
}
+ if (!annotate_schema.empty()) {
+ const std::string ext = flatbuffers::GetExtension(annotate_schema);
+ if (!(ext == reflection::SchemaExtension() || ext == "fbs")) {
+ Error("Expected a `.bfbs` or `.fbs` schema, got: " + annotate_schema);
+ }
+
+ const bool is_binary_schema = ext == reflection::SchemaExtension();
+
+ std::string schema_contents;
+ if (!flatbuffers::LoadFile(annotate_schema.c_str(),
+ /*binary=*/is_binary_schema, &schema_contents)) {
+ Error("unable to load schema: " + annotate_schema);
+ }
+
+ const uint8_t *binary_schema = nullptr;
+ uint64_t binary_schema_size = 0;
+
+ IDLOptions binary_opts;
+ binary_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
+ flatbuffers::Parser parser(binary_opts);
+
+ if (is_binary_schema) {
+ binary_schema =
+ reinterpret_cast<const uint8_t *>(schema_contents.c_str());
+ binary_schema_size = schema_contents.size();
+ } else {
+ // If we need to generate the .bfbs file from the provided schema file
+ // (.fbs)
+ ParseFile(parser, annotate_schema, schema_contents, include_directories);
+ parser.Serialize();
+
+ binary_schema = parser.builder_.GetBufferPointer();
+ binary_schema_size = parser.builder_.GetSize();
+ }
+
+ if (binary_schema == nullptr || !binary_schema_size) {
+ Error("could not parse a value binary schema from: " + annotate_schema);
+ }
+
+ // Annotate the provided files with the binary_schema.
+ AnnotateBinaries(binary_schema, binary_schema_size, annotate_schema,
+ filenames);
+
+ // We don't support doing anything else after annotating a binary.
+ return 0;
+ }
+
std::unique_ptr<flatbuffers::Parser> parser(new flatbuffers::Parser(opts));
for (auto file_it = filenames.begin(); file_it != filenames.end();
@@ -755,7 +849,7 @@
if (params_.generators[i].generateGRPC != nullptr) {
if (!params_.generators[i].generateGRPC(*parser.get(), output_path,
filebase)) {
- Error(std::string("Unable to generate GRPC interface for") +
+ Error(std::string("Unable to generate GRPC interface for ") +
params_.generators[i].lang_name);
}
} else {
diff --git a/third_party/flatbuffers/src/flatc_main.cpp b/third_party/flatbuffers/src/flatc_main.cpp
index abcab24..b4c4251 100644
--- a/third_party/flatbuffers/src/flatc_main.cpp
+++ b/third_party/flatbuffers/src/flatc_main.cpp
@@ -52,9 +52,6 @@
} // namespace flatbuffers
int main(int argc, const char *argv[]) {
- // Prevent Appveyor-CI hangs.
- flatbuffers::SetupDefaultCRTReportMode();
-
const std::string flatbuffers_version(flatbuffers::FLATBUFFERS_VERSION());
std::unique_ptr<flatbuffers::BfbsGenerator> bfbs_gen_lua =
diff --git a/third_party/flatbuffers/src/idl_gen_cpp.cpp b/third_party/flatbuffers/src/idl_gen_cpp.cpp
index ef7f60a..c1a0198 100644
--- a/third_party/flatbuffers/src/idl_gen_cpp.cpp
+++ b/third_party/flatbuffers/src/idl_gen_cpp.cpp
@@ -16,8 +16,10 @@
// independent from idl_parser, since this code is not needed for most clients
+#include <string>
#include <unordered_set>
+#include "flatbuffers/base.h"
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/flatc.h"
@@ -68,6 +70,19 @@
return guard;
}
+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 &&
+ !vector_type.struct_def->fixed && !field.native_inline;
+}
+
+static bool IsPointer(const FieldDef &field) {
+ return field.value.type.base_type == BASE_TYPE_STRUCT &&
+ !IsStruct(field.value.type);
+}
+
namespace cpp {
enum CppStandard { CPP_STD_X0 = 0, CPP_STD_11, CPP_STD_17 };
@@ -199,37 +214,66 @@
for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
}
+ // Adds code to check that the included flatbuffers.h is of the same version
+ // as the generated code. This check currently looks for exact version match,
+ // as we would guarantee that they are compatible, but in theory a newer
+ // version of flatbuffers.h should work with a old code gen if we do proper
+ // backwards support.
+ void GenFlatbuffersVersionCheck() {
+ code_ +=
+ "// Ensure the included flatbuffers.h is the same version as when this "
+ "file was";
+ code_ += "// generated, otherwise it may not be compatible.";
+ code_ += "static_assert(FLATBUFFERS_VERSION_MAJOR == " +
+ std::to_string(FLATBUFFERS_VERSION_MAJOR) + " &&";
+ code_ += " FLATBUFFERS_VERSION_MINOR == " +
+ std::to_string(FLATBUFFERS_VERSION_MINOR) + " &&";
+ code_ += " FLATBUFFERS_VERSION_REVISION == " +
+ std::to_string(FLATBUFFERS_VERSION_REVISION) + ",";
+ code_ += " \"Non-compatible flatbuffers version included\");";
+ }
+
void GenIncludeDependencies() {
- int num_includes = 0;
if (opts_.generate_object_based_api) {
for (auto it = parser_.native_included_files_.begin();
it != parser_.native_included_files_.end(); ++it) {
code_ += "#include \"" + *it + "\"";
- num_includes++;
}
}
- for (auto it = parser_.included_files_.begin();
- it != parser_.included_files_.end(); ++it) {
- if (it->second.empty()) continue;
- auto noext = flatbuffers::StripExtension(it->second);
- auto basename = flatbuffers::StripPath(noext);
- // TODO(austin): Clean this up.
- // The reflection_generated.h header is not in the reflection folder like
- // it's include path and namespace suggests. Detect this special case and
- // rewrite it.
- auto includeName =
- GeneratedFileName(opts_.include_prefix,
- opts_.keep_include_path ? noext : basename, opts_);
+ // Get the directly included file of the file being parsed.
+ std::vector<IncludedFile> included_files(parser_.GetIncludedFiles());
- if (includeName == "reflection/reflection_generated.h") {
- includeName = "flatbuffers/reflection_generated.h";
+ // We are safe to sort them alphabetically, since there shouldn't be any
+ // interdependence between them.
+ std::stable_sort(included_files.begin(), included_files.end());
+
+ for (const IncludedFile &included_file : included_files) {
+ // Get the name of the included file as defined by the schema, and strip
+ // the .fbs extension.
+ const std::string name_without_ext =
+ flatbuffers::StripExtension(included_file.schema_name);
+
+ // If we are told to keep the prefix of the included schema, leave it
+ // unchanged, otherwise strip the leading path off so just the "basename"
+ // of the include is retained.
+ const std::string basename =
+ opts_.keep_prefix ? name_without_ext
+ : flatbuffers::StripPath(name_without_ext);
+
+ std::string include_name =
+ GeneratedFileName(opts_.include_prefix, basename, opts_);
+
+ if (include_name == "reflection/reflection_generated.h") {
+ include_name = "flatbuffers/reflection_generated.h";
}
- code_ += "#include \"" + includeName + "\"";
- num_includes++;
+ code_ += "#include \"" + include_name + "\"";
}
- if (num_includes) code_ += "";
+
+ if (!parser_.native_included_files_.empty() || !included_files.empty()) {
+ code_ += "";
+ }
}
void GenExtraIncludes() {
@@ -295,6 +339,8 @@
code_ += "#include \"flatbuffers/flatbuffers.h\"";
code_ += "";
+ GenFlatbuffersVersionCheck();
+ code_ += "";
SetNameSpace(struct_def.defined_namespace);
auto name = Name(struct_def);
@@ -357,8 +403,11 @@
code_ += "#include \"flatbuffers/flatbuffers.h\"";
if (parser_.uses_flexbuffers_) {
code_ += "#include \"flatbuffers/flexbuffers.h\"";
+ code_ += "#include \"flatbuffers/flex_flat_util.h\"";
}
code_ += "";
+ GenFlatbuffersVersionCheck();
+ code_ += "";
if (opts_.include_dependence_headers) { GenIncludeDependencies(); }
GenExtraIncludes();
@@ -852,7 +901,9 @@
}
} else {
const auto nn = WrapNativeNameInNameSpace(*type.struct_def, opts_);
- return forcopy ? nn : GenTypeNativePtr(nn, &field, false);
+ return (forcopy || field.native_inline)
+ ? nn
+ : GenTypeNativePtr(nn, &field, false);
}
}
case BASE_TYPE_UNION: {
@@ -1838,9 +1889,8 @@
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 bool is_ptr =
- (vec_type.base_type == BASE_TYPE_STRUCT && !IsStruct(vec_type)) ||
- (cpp_type && cpp_ptr_type->constant != "naked");
+ const bool is_ptr = IsVectorOfPointers(field) ||
+ (cpp_type && cpp_ptr_type->constant != "naked");
if (is_ptr) { return true; }
}
}
@@ -1964,9 +2014,8 @@
? cpp_type->constant
: GenTypeNative(vec_type, /*invector*/ true,
field, /*forcopy*/ true);
- const bool is_ptr =
- (vec_type.base_type == BASE_TYPE_STRUCT && !IsStruct(vec_type)) ||
- (cpp_type && cpp_ptr_type->constant != "naked");
+ const bool is_ptr = IsVectorOfPointers(field) ||
+ (cpp_type && cpp_ptr_type->constant != "naked");
CodeWriter cw(" ");
cw.SetValue("FIELD", Name(field));
cw.SetValue("TYPE", type_name);
@@ -2031,19 +2080,39 @@
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
+ const auto accessor = Name(field) + accessSuffix;
+ const auto lhs_accessor = "lhs." + accessor;
+ 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 ||
field.value.type.element != BASE_TYPE_UTYPE)) {
if (!compare_op.empty()) { compare_op += " &&\n "; }
- auto accessor = Name(field) + accessSuffix;
if (struct_def.fixed || field.native_inline ||
field.value.type.base_type != BASE_TYPE_STRUCT) {
- compare_op += "(lhs." + accessor + " == rhs." + accessor + ")";
+ // If the field is a vector of tables, the table need to be compared
+ // by value, instead of by the default unique_ptr == operator which
+ // compares by address.
+ if (IsVectorOfPointers(field)) {
+ const auto type =
+ GenTypeNative(field.value.type.VectorType(), true, field);
+ const auto equal_length =
+ lhs_accessor + ".size() == " + rhs_accessor + ".size()";
+ const auto elements_equal =
+ "std::equal(" + lhs_accessor + ".cbegin(), " + lhs_accessor +
+ ".cend(), " + rhs_accessor + ".cbegin(), [](" + type +
+ " const &a, " + type +
+ " const &b) { return (a == b) || (a && b && *a == *b); })";
+
+ compare_op += "(" + equal_length + " && " + elements_equal + ")";
+ } else {
+ compare_op += "(" + lhs_accessor + " == " + rhs_accessor + ")";
+ }
} else {
// Deep compare of std::unique_ptr. Null is not equal to empty.
std::string both_null =
- "(lhs." + accessor + " == rhs." + accessor + ")";
+ "(" + lhs_accessor + " == " + rhs_accessor + ")";
std::string not_null_and_equal = "(lhs." + accessor + " && rhs." +
accessor + " && *lhs." + accessor +
" == *rhs." + accessor + ")";
@@ -2259,7 +2328,7 @@
// @TODO: Mby make this decisions more universal? How?
code_.SetValue("U_GET_TYPE",
- EscapeKeyword(field.name + UnionTypeFieldSuffix()));
+ EscapeKeyword(Name(field) + UnionTypeFieldSuffix()));
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(u->defined_namespace,
GetEnumValUse(*u, ev)));
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
@@ -2932,7 +3001,8 @@
return ptype + "(new " + name + "(*" + val + "))";
}
} else {
- const auto ptype = GenTypeNativePtr(
+ std::string ptype = afield.native_inline ? "*" : "";
+ ptype += GenTypeNativePtr(
WrapNativeNameInNameSpace(*type.struct_def, opts_), &afield,
true);
return ptype + "(" + val + "->UnPack(_resolver))";
@@ -2960,7 +3030,8 @@
if (field.value.type.element == BASE_TYPE_UTYPE) {
name = StripUnionType(Name(field));
}
- code += "{ _o->" + name + ".resize(_e->size()); ";
+ const std::string vector_field = "_o->" + name;
+ code += "{ " + vector_field + ".resize(_e->size()); ";
if (!field.value.type.enum_def && !IsBool(field.value.type.element) &&
IsOneByte(field.value.type.element)) {
// For vectors of bytes, std::copy is used to improve performance.
@@ -3000,7 +3071,7 @@
// (*resolver)(&_o->field, (hash_value_t)(_e));
// else
// _o->field = nullptr;
- code += "//vector resolver, " + PtrType(&field) + "\n";
+ code += "/*vector resolver, " + PtrType(&field) + "*/ ";
code += "if (_resolver) ";
code += "(*_resolver)";
code += "(reinterpret_cast<void **>(&_o->" + name + "[_i]" +
@@ -3017,9 +3088,7 @@
code += "/* else do nothing */";
}
} else {
- const bool is_pointer =
- field.value.type.VectorType().base_type == BASE_TYPE_STRUCT &&
- !IsStruct(field.value.type.VectorType());
+ const bool is_pointer = IsVectorOfPointers(field);
if (is_pointer) {
code += "if(_o->" + name + "[_i]" + ") { ";
code += indexing + "->UnPackTo(_o->" + name +
@@ -3031,7 +3100,7 @@
field);
if (is_pointer) { code += "; }"; }
}
- code += "; } }";
+ code += "; } } else { " + vector_field + ".resize(0); }";
}
break;
}
@@ -3059,7 +3128,7 @@
// (*resolver)(&_o->field, (hash_value_t)(_e));
// else
// _o->field = nullptr;
- code += "//scalar resolver, " + PtrType(&field) + " \n";
+ code += "/*scalar resolver, " + PtrType(&field) + "*/ ";
code += "if (_resolver) ";
code += "(*_resolver)";
code += "(reinterpret_cast<void **>(&_o->" + Name(field) + "), ";
@@ -3076,17 +3145,21 @@
} else {
// Generate code for assigning the value, of the form:
// _o->field = value;
- const bool is_pointer =
- field.value.type.base_type == BASE_TYPE_STRUCT &&
- !IsStruct(field.value.type);
+ const bool is_pointer = IsPointer(field);
+
+ const std::string out_field = "_o->" + Name(field);
+
if (is_pointer) {
- code += "{ if(_o->" + Name(field) + ") { ";
- code += "_e->UnPackTo(_o->" + Name(field) + ".get(), _resolver);";
+ code += "{ if(" + out_field + ") { ";
+ code += "_e->UnPackTo(" + out_field + ".get(), _resolver);";
code += " } else { ";
}
- code += "_o->" + Name(field) + " = ";
+ code += out_field + " = ";
code += GenUnpackVal(field.value.type, "_e", false, field) + ";";
- if (is_pointer) { code += " } }"; }
+ if (is_pointer) {
+ code += " } } else if (" + out_field + ") { " + out_field +
+ ".reset(); }";
+ }
}
break;
}
@@ -3192,9 +3265,13 @@
code += "(" + value + ".size(), ";
code += "[](size_t i, _VectorArgs *__va) { ";
code += "return Create" + vector_type.struct_def->name;
- code += "(*__va->__fbb, __va->_" + value + "[i]" +
- GenPtrGet(field) + ", ";
- code += "__va->__rehasher); }, &_va )";
+ code += "(*__va->__fbb, ";
+ if (field.native_inline) {
+ code += "&(__va->_" + value + "[i])";
+ } else {
+ code += "__va->_" + value + "[i]" + GenPtrGet(field);
+ }
+ code += ", __va->__rehasher); }, &_va )";
}
break;
}
@@ -3253,7 +3330,8 @@
// If set_empty_vectors_to_null option is enabled, for optional fields,
// check to see if there actually is any data in _o->field before
// attempting to access it.
- if (opts_.set_empty_vectors_to_null && !field.IsRequired()) {
+ if (field.attributes.Lookup("nested_flatbuffer") ||
+ (opts_.set_empty_vectors_to_null && !field.IsRequired())) {
code = value + ".size() ? " + code + " : 0";
}
break;
@@ -3276,14 +3354,15 @@
} else if (field.native_inline) {
code += "&" + value;
} else {
- code += value + " ? " + value + GenPtrGet(field) + " : 0";
+ code += value + " ? " + value + GenPtrGet(field) + " : nullptr";
}
} else {
// _o->field ? CreateT(_fbb, _o->field.get(), _rehasher);
const auto type = field.value.type.struct_def->name;
code += value + " ? Create" + type;
- code += "(_fbb, " + value + GenPtrGet(field) + ", _rehasher)";
- code += " : 0";
+ code += "(_fbb, " + value;
+ if (!field.native_inline) code += GenPtrGet(field);
+ code += ", _rehasher) : 0";
}
break;
}
@@ -3460,7 +3539,7 @@
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto field = *it;
- const auto field_name = field->name + "_";
+ const auto field_name = Name(*field) + "_";
if (first_in_init_list) {
first_in_init_list = false;
diff --git a/third_party/flatbuffers/src/idl_gen_csharp.cpp b/third_party/flatbuffers/src/idl_gen_csharp.cpp
index cb605de..fa67eaf 100644
--- a/third_party/flatbuffers/src/idl_gen_csharp.cpp
+++ b/third_party/flatbuffers/src/idl_gen_csharp.cpp
@@ -226,7 +226,7 @@
if (needs_includes) {
code += "using global::System;\n";
code += "using global::System.Collections.Generic;\n";
- code += "using global::FlatBuffers;\n\n";
+ code += "using global::Google.FlatBuffers;\n\n";
}
code += classcode;
if (!namespace_name.empty()) { code += "\n}\n"; }
@@ -459,20 +459,24 @@
}
}
+ std::string GetObjectConstructor(flatbuffers::StructDef &struct_def,
+ const std::string &data_buffer,
+ const std::string &offset) const {
+ // Use the generated type directly, to properly handle default values that
+ // might not be written to the buffer.
+ return "new " + Name(struct_def) + "().__assign(" + offset + ", " +
+ data_buffer + ")";
+ }
+
// Returns the function name that is able to read a value of the given type.
- std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field,
+ std::string GenGetterForLookupByKey(flatbuffers::StructDef &struct_def,
+ flatbuffers::FieldDef *key_field,
const std::string &data_buffer,
- const char *num = nullptr) const {
- auto type = key_field->value.type;
- auto dest_mask = "";
- auto dest_cast = DestinationCast(type);
- auto getter = data_buffer + ".Get";
- if (GenTypeBasic(type, false) != "byte") {
- getter += ConvertCase(GenTypeBasic(type, false), Case::kUpperCamel);
- }
- getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")" +
- dest_mask;
- return getter;
+ const std::string &offset) const {
+ // Use the generated type directly, to properly handle default values that
+ // might not be written to the buffer.
+ return GetObjectConstructor(struct_def, data_buffer, offset) + "." +
+ Name(*key_field);
}
// Direct mutation is only allowed for scalar fields.
@@ -605,37 +609,15 @@
return key_offset;
}
- std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) const {
- std::string key_getter = " ";
- key_getter += "int tableOffset = Table.";
- key_getter += "__indirect(vectorLocation + 4 * (start + middle)";
- key_getter += ", bb);\n ";
- if (IsString(key_field->value.type)) {
- key_getter += "int comp = Table.";
- key_getter += "CompareStrings(";
- key_getter += GenOffsetGetter(key_field);
- key_getter += ", byteKey, bb);\n";
- } else {
- auto get_val = GenGetterForLookupByKey(key_field, "bb");
- key_getter += "int comp = " + get_val + ".CompareTo(key);\n";
- }
- return key_getter;
- }
-
- std::string GenKeyGetter(flatbuffers::FieldDef *key_field) const {
- std::string key_getter = "";
- auto data_buffer = "builder.DataBuffer";
- if (IsString(key_field->value.type)) {
- key_getter += "Table.CompareStrings(";
- key_getter += GenOffsetGetter(key_field, "o1") + ", ";
- key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")";
- } else {
- auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1");
- key_getter += field_getter;
- field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2");
- key_getter += ".CompareTo(" + field_getter + ")";
- }
- return key_getter;
+ std::string GenKeyGetter(flatbuffers::StructDef &struct_def,
+ flatbuffers::FieldDef *key_field) const {
+ // Get the getter for the key of the struct.
+ return GenGetterForLookupByKey(struct_def, key_field, "builder.DataBuffer",
+ "builder.DataBuffer.Length - o1.Value") +
+ ".CompareTo(" +
+ GenGetterForLookupByKey(struct_def, key_field, "builder.DataBuffer",
+ "builder.DataBuffer.Length - o2.Value") +
+ ")";
}
void GenStruct(StructDef &struct_def, std::string *code_ptr,
@@ -669,11 +651,11 @@
code += " public ByteBuffer ByteBuffer { get { return __p.bb; } }\n";
if (!struct_def.fixed) {
- // Generate verson check method.
+ // Generate version check method.
// Force compile time error if not using the same version runtime.
code += " public static void ValidateVersion() {";
code += " FlatBufferConstants.";
- code += "FLATBUFFERS_2_0_0(); ";
+ code += "FLATBUFFERS_2_0_8(); ";
code += "}\n";
// Generate a special accessor for the table that when used as the root
@@ -914,7 +896,9 @@
code += member_suffix;
code += "}\n";
if (IsVector(field.value.type)) {
- code += " public int " + Name(field);
+ auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
+ code += " public int " + camel_name;
code += "Length";
code += " { get";
code += offset_prefix;
@@ -1238,6 +1222,8 @@
code += "); return ";
code += "builder.EndVector(); }\n";
+ // add Create...VectorBlock() overloads for T[], ArraySegment<T> and
+ // IntPtr
code += " public static VectorOffset ";
code += "Create";
code += Name(field);
@@ -1248,6 +1234,26 @@
code += ", data.Length, ";
code += NumToString(alignment);
code += "); builder.Add(data); return builder.EndVector(); }\n";
+
+ code += " public static VectorOffset ";
+ code += "Create";
+ code += Name(field);
+ code += "VectorBlock(FlatBufferBuilder builder, ";
+ code += "ArraySegment<" + GenTypeBasic(vector_type) + "> data) ";
+ code += "{ builder.StartVector(";
+ code += NumToString(elem_size);
+ code += ", data.Count, ";
+ code += NumToString(alignment);
+ code += "); builder.Add(data); return builder.EndVector(); }\n";
+
+ code += " public static VectorOffset ";
+ code += "Create";
+ code += Name(field);
+ code += "VectorBlock(FlatBufferBuilder builder, ";
+ code += "IntPtr dataPtr, int sizeInBytes) ";
+ code += "{ builder.StartVector(1, sizeInBytes, 1); ";
+ code += "builder.Add<" + GenTypeBasic(vector_type) +
+ ">(dataPtr, sizeInBytes); return builder.EndVector(); }\n";
}
// Generate a method to start a vector, data to be added manually
// after.
@@ -1300,9 +1306,10 @@
code += "(FlatBufferBuilder builder, ";
code += "Offset<" + struct_def.name + ">";
code += "[] offsets) {\n";
- code += " Array.Sort(offsets, (Offset<" + struct_def.name +
- "> o1, Offset<" + struct_def.name + "> o2) => " +
- GenKeyGetter(key_field);
+ code += " Array.Sort(offsets,\n";
+ code += " (Offset<" + struct_def.name + "> o1, Offset<" +
+ struct_def.name + "> o2) =>\n";
+ code += " " + GenKeyGetter(struct_def, key_field);
code += ");\n";
code += " return builder.CreateVectorOfTables(offsets);\n }\n";
@@ -1311,16 +1318,20 @@
code += "int vectorLocation, ";
code += GenTypeGet(key_field->value.type);
code += " key, ByteBuffer bb) {\n";
- if (IsString(key_field->value.type)) {
- code += " byte[] byteKey = ";
- code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
- }
+ code +=
+ " " + struct_def.name + " obj_ = new " + struct_def.name + "();\n";
code += " int span = ";
code += "bb.GetInt(vectorLocation - 4);\n";
code += " int start = 0;\n";
code += " while (span != 0) {\n";
code += " int middle = span / 2;\n";
- code += GenLookupKeyGetter(key_field);
+ code +=
+ " int tableOffset = Table.__indirect(vectorLocation + 4 * "
+ "(start + middle), bb);\n";
+
+ code += " obj_.__assign(tableOffset, bb);\n";
+ code +=
+ " int comp = obj_." + Name(*key_field) + ".CompareTo(key);\n";
code += " if (comp > 0) {\n";
code += " span = middle;\n";
code += " } else if (comp < 0) {\n";
@@ -1328,9 +1339,7 @@
code += " start += middle;\n";
code += " span -= middle;\n";
code += " } else {\n";
- code += " return ";
- code += "new " + struct_def.name + "()";
- code += ".__assign(tableOffset, bb);\n";
+ code += " return obj_;\n";
code += " }\n }\n";
code += " return null;\n";
code += " }\n";
@@ -1454,8 +1463,10 @@
}
code += "\n";
// Pack()
- code += " public static int Pack(FlatBuffers.FlatBufferBuilder builder, " +
- union_name + " _o) {\n";
+ code +=
+ " public static int Pack(Google.FlatBuffers.FlatBufferBuilder "
+ "builder, " +
+ union_name + " _o) {\n";
code += " switch (_o.Type) {\n";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
@@ -1566,6 +1577,7 @@
void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string *code_ptr,
const std::string &camel_name,
+ const std::string &camel_name_short,
bool is_vector) const {
auto &code = *code_ptr;
std::string varialbe_name = "_o." + camel_name;
@@ -1584,10 +1596,10 @@
code += indent + varialbe_name + " = new ";
}
code += NamespacedName(enum_def) + "Union();\n";
- code += indent + varialbe_name + ".Type = this." + camel_name + "Type" +
- type_suffix + ";\n";
- code +=
- indent + "switch (this." + camel_name + "Type" + type_suffix + ") {\n";
+ code += indent + varialbe_name + ".Type = this." + camel_name_short +
+ "Type" + type_suffix + ";\n";
+ code += indent + "switch (this." + camel_name_short + "Type" + type_suffix +
+ ") {\n";
for (auto eit = enum_def.Vals().begin(); eit != enum_def.Vals().end();
++eit) {
auto &ev = **eit;
@@ -1633,6 +1645,8 @@
auto &field = **it;
if (field.deprecated) continue;
auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
+ auto camel_name_short = Name(field);
auto start = " _o." + camel_name + " = ";
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
@@ -1666,7 +1680,7 @@
code += " for (var _j = 0; _j < this." + camel_name +
"Length; ++_j) {\n";
GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
- camel_name, true);
+ camel_name, camel_name_short, true);
code += " }\n";
} else if (field.value.type.element != BASE_TYPE_UTYPE) {
auto fixed = field.value.type.struct_def == nullptr;
@@ -1687,7 +1701,7 @@
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_UNION: {
GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
- camel_name, false);
+ camel_name, camel_name_short, false);
break;
}
default: {
@@ -1707,6 +1721,8 @@
auto &field = **it;
if (field.deprecated) continue;
auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
+ auto camel_name_short = Name(field);
// pre
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
@@ -1782,7 +1798,7 @@
code += " var " + array_name + " = _o." + property_name +
".ToArray();\n";
}
- code += " _" + field.name + " = Create" + camel_name +
+ code += " _" + field.name + " = Create" + camel_name_short +
"Vector(builder, " + array_name + ");\n";
code += " }\n";
} else {
@@ -1794,7 +1810,7 @@
camel_name + "[_j]);";
code += " var _" + field.name + " = default(VectorOffset);\n";
code += " if (_o." + camel_name + " != null) {\n";
- code += " Start" + camel_name + "Vector(builder, _o." +
+ code += " Start" + camel_name_short + "Vector(builder, _o." +
camel_name + ".Count);\n";
code += " for (var _j = _o." + camel_name +
".Count - 1; _j >= 0; --_j) { " + pack_method + " }\n";
@@ -1840,6 +1856,7 @@
auto &field = **it;
if (field.deprecated) continue;
auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (struct_def.fixed) {
@@ -2094,6 +2111,7 @@
auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
if (field.IsScalarOptional()) type_name += "?";
auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
if (opts.cs_gen_json_serializer) {
if (IsUnion(field.value.type)) {
auto utype_name = NamespacedName(*field.value.type.enum_def);
@@ -2159,7 +2177,9 @@
if (field.deprecated) continue;
if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
if (field.value.type.element == BASE_TYPE_UTYPE) continue;
- code += " this." + Name(field) + " = ";
+ auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
+ code += " this." + camel_name + " = ";
auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
if (IsScalar(field.value.type.base_type)) {
code += GenDefaultValue(field) + ";\n";
diff --git a/third_party/flatbuffers/src/idl_gen_dart.cpp b/third_party/flatbuffers/src/idl_gen_dart.cpp
index ff2c1a5..0bf230d 100644
--- a/third_party/flatbuffers/src/idl_gen_dart.cpp
+++ b/third_party/flatbuffers/src/idl_gen_dart.cpp
@@ -21,26 +21,57 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
namespace dart {
+namespace {
+
+static Namer::Config DartDefaultConfig() {
+ return { /*types=*/Case::kUpperCamel,
+ /*constants=*/Case::kScreamingSnake,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kUnknown, // unused.
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kSnake2,
+ /*namespace_seperator=*/".",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"$",
+ /*keyword_suffix=*/"",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".dart" };
+}
+
+static std::set<std::string> DartKeywords() {
+ // see https://www.dartlang.org/guides/language/language-tour#keywords
+ // yield*, async*, and sync* shouldn't be proble
+ return {
+ "abstract", "else", "import", "show", "as", "enum",
+ "in", "static", "assert", "export", "interface", "super",
+ "async", "extends", "is", "switch", "await", "extension",
+ "late", "sync", "break", "external", "library", "this",
+ "case", "factory", "mixin", "throw", "catch", "false",
+ "new", "true", "class", "final", "null", "try",
+ "const", "finally", "on", "typedef", "continue", "for",
+ "operator", "var", "covariant", "Function", "part", "void",
+ "default", "get", "required", "while", "deferred", "hide",
+ "rethrow", "with", "do", "if", "return", "yield",
+ "dynamic", "implements", "set",
+ };
+}
+} // namespace
+
const std::string _kFb = "fb";
-// see https://www.dartlang.org/guides/language/language-tour#keywords
-// yeild*, async*, and sync* shouldn't be problems anyway but keeping them in
-static const char *keywords[] = {
- "abstract", "deferred", "if", "super", "as", "do",
- "implements", "switch", "assert", "dynamic", "import", "sync*",
- "async", "else", "in", "this", "async*", "enum",
- "is", "throw", "await", "export", "library", "true",
- "break", "external", "new", "try", "case", "extends",
- "null", "typedef", "catch", "factory", "operator", "var",
- "class", "false", "part", "void", "const", "final",
- "rethrow", "while", "continue", "finally", "return", "with",
- "covariant", "for", "set", "yield", "default", "get",
- "static", "yield*"
-};
// Iterate through all definitions we haven't generate code for (enums, structs,
// and tables) and output them to a single file.
@@ -50,14 +81,16 @@
DartGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
- : BaseGenerator(parser, path, file_name, "", ".", "dart") {}
+ : BaseGenerator(parser, path, file_name, "", ".", "dart"),
+ namer_(WithFlagOptions(DartDefaultConfig(), parser.opts, path),
+ DartKeywords()) {}
// Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file.
bool generate() {
std::string code;
namespace_code_map namespace_code;
- GenerateEnums(&namespace_code);
- GenerateStructs(&namespace_code);
+ GenerateEnums(namespace_code);
+ GenerateStructs(namespace_code);
for (auto kv = namespace_code.begin(); kv != namespace_code.end(); ++kv) {
code.clear();
@@ -75,31 +108,23 @@
for (auto kv2 = namespace_code.begin(); kv2 != namespace_code.end();
++kv2) {
if (kv2->first != kv->first) {
- code +=
- "import '" +
- GeneratedFileName(
- "./",
- file_name_ + (!kv2->first.empty() ? "_" + kv2->first : ""),
- parser_.opts) +
- "' as " + ImportAliasName(kv2->first) + ";\n";
+ code += "import './" + Filename(kv2->first, /*path=*/false) +
+ "' as " + ImportAliasName(kv2->first) + ";\n";
}
}
code += "\n";
code += kv->second;
- if (!SaveFile(
- GeneratedFileName(
- path_,
- file_name_ + (!kv->first.empty() ? "_" + kv->first : ""),
- parser_.opts)
- .c_str(),
- code, false)) {
- return false;
- }
+ if (!SaveFile(Filename(kv->first).c_str(), code, false)) { return false; }
}
return true;
}
+ std::string Filename(const std::string &suffix, bool path = true) const {
+ return (path ? path_ : "") +
+ namer_.File(file_name_ + (suffix.empty() ? "" : "_" + suffix));
+ }
+
private:
static std::string ImportAliasName(const std::string &ns) {
std::string ret;
@@ -113,64 +138,15 @@
return ret;
}
- static std::string BuildNamespaceName(const Namespace &ns) {
- if (ns.components.empty()) { return ""; }
- std::stringstream sstream;
- std::copy(ns.components.begin(), ns.components.end() - 1,
- std::ostream_iterator<std::string>(sstream, "."));
-
- auto ret = sstream.str() + ns.components.back();
- for (size_t i = 0; i < ret.size(); i++) {
- auto lower = CharToLower(ret[i]);
- if (lower != ret[i]) {
- ret[i] = lower;
- if (i != 0 && ret[i - 1] != '.') {
- ret.insert(i, "_");
- i++;
- }
- }
- }
- // std::transform(ret.begin(), ret.end(), ret.begin(), CharToLower);
- return ret;
- }
-
- void GenIncludeDependencies(std::string *code,
- const std::string &the_namespace) {
- for (auto it = parser_.included_files_.begin();
- it != parser_.included_files_.end(); ++it) {
- if (it->second.empty()) continue;
-
- auto noext = flatbuffers::StripExtension(it->second);
- auto basename = flatbuffers::StripPath(noext);
-
- *code +=
- "import '" +
- GeneratedFileName(
- "", basename + (the_namespace == "" ? "" : "_" + the_namespace),
- parser_.opts) +
- "';\n";
- }
- }
-
- static std::string EscapeKeyword(const std::string &name) {
- for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
- if (name == keywords[i]) {
- return ConvertCase(name + "_", Case::kLowerCamel);
- }
- }
-
- return ConvertCase(name, Case::kLowerCamel);
- }
-
- void GenerateEnums(namespace_code_map *namespace_code) {
+ void GenerateEnums(namespace_code_map &namespace_code) {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
auto &enum_def = **it;
- GenEnum(enum_def, namespace_code); // enum_code_ptr);
+ GenEnum(enum_def, namespace_code);
}
}
- void GenerateStructs(namespace_code_map *namespace_code) {
+ void GenerateStructs(namespace_code_map &namespace_code) {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
@@ -180,80 +156,50 @@
// Generate a documentation comment, if available.
static void GenDocComment(const std::vector<std::string> &dc,
- std::string *code_ptr,
- const std::string &extra_lines,
- const char *indent = nullptr) {
- if (dc.empty() && extra_lines.empty()) {
- // Don't output empty comment blocks with 0 lines of comment content.
- return;
- }
-
- auto &code = *code_ptr;
-
+ const char *indent, std::string &code) {
for (auto it = dc.begin(); it != dc.end(); ++it) {
if (indent) code += indent;
code += "/// " + *it + "\n";
}
- if (!extra_lines.empty()) {
- if (!dc.empty()) {
- if (indent) code += indent;
- code += "///\n";
- }
- if (indent) code += indent;
- std::string::size_type start = 0;
- for (;;) {
- auto end = extra_lines.find('\n', start);
- if (end != std::string::npos) {
- code += "/// " + extra_lines.substr(start, end - start) + "\n";
- start = end + 1;
- } else {
- code += "/// " + extra_lines.substr(start) + "\n";
- break;
- }
- }
- }
- }
-
- static void GenDocComment(std::string *code_ptr,
- const std::string &extra_lines) {
- GenDocComment(std::vector<std::string>(), code_ptr, extra_lines);
}
// Generate an enum declaration and an enum string lookup table.
- void GenEnum(EnumDef &enum_def, namespace_code_map *namespace_code) {
+ void GenEnum(EnumDef &enum_def, namespace_code_map &namespace_code) {
if (enum_def.generated) return;
- auto ns = BuildNamespaceName(*enum_def.defined_namespace);
- std::string code;
- GenDocComment(enum_def.doc_comment, &code, "");
+ std::string &code =
+ namespace_code[namer_.Namespace(*enum_def.defined_namespace)];
+ GenDocComment(enum_def.doc_comment, "", code);
- auto name = enum_def.is_union ? enum_def.name + "TypeId" : enum_def.name;
+ const std::string enum_type =
+ namer_.Type(enum_def) + (enum_def.is_union ? "TypeId" : "");
const bool is_bit_flags =
enum_def.attributes.Lookup("bit_flags") != nullptr;
// The flatbuffer schema language allows bit flag enums to potentially have
// a default value of zero, even if it's not a valid enum value...
const bool permit_zero = is_bit_flags;
- code += "class " + name + " {\n";
+ code += "class " + enum_type + " {\n";
code += " final int value;\n";
- code += " const " + name + "._(this.value);\n\n";
- code += " factory " + name + ".fromValue(int value) {\n";
+ code += " const " + enum_type + "._(this.value);\n\n";
+ code += " factory " + enum_type + ".fromValue(int value) {\n";
code += " final result = values[value];\n";
code += " if (result == null) {\n";
if (permit_zero) {
code += " if (value == 0) {\n";
- code += " return " + name + "._(0);\n";
+ code += " return " + enum_type + "._(0);\n";
code += " } else {\n";
}
code += " throw StateError('Invalid value $value for bit flag enum ";
- code += name + "');\n";
+ code += enum_type + "');\n";
if (permit_zero) { code += " }\n"; }
code += " }\n";
code += " return result;\n";
code += " }\n\n";
- code += " static " + name + "? _createOrNull(int? value) => \n";
- code += " value == null ? null : " + name + ".fromValue(value);\n\n";
+ code += " static " + enum_type + "? _createOrNull(int? value) => \n";
+ code +=
+ " value == null ? null : " + enum_type + ".fromValue(value);\n\n";
// this is meaningless for bit_flags
// however, note that unlike "regular" dart enums this enum can still have
@@ -271,53 +217,52 @@
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
+ const auto enum_var = namer_.Variant(ev);
if (!ev.doc_comment.empty()) {
if (it != enum_def.Vals().begin()) { code += '\n'; }
- GenDocComment(ev.doc_comment, &code, "", " ");
+ GenDocComment(ev.doc_comment, " ", code);
}
- code += " static const " + name + " " + ev.name + " = " + name + "._(" +
- enum_def.ToString(ev) + ");\n";
+ code += " static const " + enum_type + " " + enum_var + " = " +
+ enum_type + "._(" + enum_def.ToString(ev) + ");\n";
}
- code += " static const Map<int, " + name + "> values = {\n";
+ code += " static const Map<int, " + enum_type + "> values = {\n";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
+ const auto enum_var = namer_.Variant(ev);
if (it != enum_def.Vals().begin()) code += ",\n";
- code += " " + enum_def.ToString(ev) + ": " + ev.name;
+ code += " " + enum_def.ToString(ev) + ": " + enum_var;
}
code += "};\n\n";
- code += " static const " + _kFb + ".Reader<" + name + "> reader = _" +
- name + "Reader();\n\n";
+ code += " static const " + _kFb + ".Reader<" + enum_type + "> reader = _" +
+ enum_type + "Reader();\n\n";
code += " @override\n";
code += " String toString() {\n";
- code += " return '" + name + "{value: $value}';\n";
+ code += " return '" + enum_type + "{value: $value}';\n";
code += " }\n";
code += "}\n\n";
- GenEnumReader(enum_def, name, &code);
- (*namespace_code)[ns] += code;
+ GenEnumReader(enum_def, enum_type, code);
}
- void GenEnumReader(EnumDef &enum_def, const std::string &name,
- std::string *code_ptr) {
- auto &code = *code_ptr;
-
- code += "class _" + name + "Reader extends " + _kFb + ".Reader<" + name +
- "> {\n";
- code += " const _" + name + "Reader();\n\n";
+ void GenEnumReader(EnumDef &enum_def, const std::string &enum_type,
+ std::string &code) {
+ code += "class _" + enum_type + "Reader extends " + _kFb + ".Reader<" +
+ enum_type + "> {\n";
+ code += " const _" + enum_type + "Reader();\n\n";
code += " @override\n";
- code += " int get size => 1;\n\n";
+ code += " int get size => " + EnumSize(enum_def.underlying_type) + ";\n\n";
code += " @override\n";
- code +=
- " " + name + " read(" + _kFb + ".BufferContext bc, int offset) =>\n";
- code += " " + name + ".fromValue(const " + _kFb + "." +
+ code += " " + enum_type + " read(" + _kFb +
+ ".BufferContext bc, int offset) =>\n";
+ code += " " + enum_type + ".fromValue(const " + _kFb + "." +
GenType(enum_def.underlying_type) + "Reader().read(bc, offset));\n";
code += "}\n\n";
}
- static std::string GenType(const Type &type) {
+ std::string GenType(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_BOOL: return "Bool";
case BASE_TYPE_CHAR: return "Int8";
@@ -333,12 +278,30 @@
case BASE_TYPE_DOUBLE: return "Float64";
case BASE_TYPE_STRING: return "String";
case BASE_TYPE_VECTOR: return GenType(type.VectorType());
- case BASE_TYPE_STRUCT: return type.struct_def->name;
- case BASE_TYPE_UNION: return type.enum_def->name + "TypeId";
+ case BASE_TYPE_STRUCT: return namer_.Type(*type.struct_def);
+ case BASE_TYPE_UNION: return namer_.Type(*type.enum_def) + "TypeId";
default: return "Table";
}
}
+ static std::string EnumSize(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_BOOL:
+ case BASE_TYPE_CHAR:
+ case BASE_TYPE_UTYPE:
+ case BASE_TYPE_UCHAR: return "1";
+ case BASE_TYPE_SHORT:
+ case BASE_TYPE_USHORT: return "2";
+ case BASE_TYPE_INT:
+ case BASE_TYPE_UINT:
+ case BASE_TYPE_FLOAT: return "4";
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG:
+ case BASE_TYPE_DOUBLE: return "8";
+ default: return "1";
+ }
+ }
+
std::string GenReaderTypeName(const Type &type, Namespace *current_namespace,
const FieldDef &def,
bool parent_is_vector = false, bool lazy = true,
@@ -378,11 +341,11 @@
std::string struct_type_suffix = "") {
if (type.enum_def) {
if (type.enum_def->is_union && type.base_type != BASE_TYPE_UNION) {
- return type.enum_def->name + "TypeId";
+ return namer_.Type(*type.enum_def) + "TypeId";
} else if (type.enum_def->is_union) {
return "dynamic";
} else if (type.base_type != BASE_TYPE_VECTOR) {
- return type.enum_def->name;
+ return namer_.Type(*type.enum_def);
}
}
@@ -400,8 +363,9 @@
case BASE_TYPE_DOUBLE: return "double";
case BASE_TYPE_STRING: return "String";
case BASE_TYPE_STRUCT:
- return MaybeWrapNamespace(type.struct_def->name + struct_type_suffix,
- current_namespace, def);
+ return MaybeWrapNamespace(
+ namer_.Type(*type.struct_def) + struct_type_suffix,
+ current_namespace, def);
case BASE_TYPE_VECTOR:
return "List<" +
GenDartTypeName(type.VectorType(), current_namespace, def,
@@ -420,21 +384,19 @@
return typeName;
}
- static const std::string MaybeWrapNamespace(const std::string &type_name,
- Namespace *current_ns,
- const FieldDef &field) {
- auto curr_ns_str = BuildNamespaceName(*current_ns);
- std::string field_ns_str = "";
- if (field.value.type.struct_def) {
- field_ns_str +=
- BuildNamespaceName(*field.value.type.struct_def->defined_namespace);
- } else if (field.value.type.enum_def) {
- field_ns_str +=
- BuildNamespaceName(*field.value.type.enum_def->defined_namespace);
- }
+ std::string MaybeWrapNamespace(const std::string &type_name,
+ Namespace *current_ns,
+ const FieldDef &field) const {
+ const std::string current_namespace = namer_.Namespace(*current_ns);
+ const std::string field_namespace =
+ field.value.type.struct_def
+ ? namer_.Namespace(*field.value.type.struct_def->defined_namespace)
+ : field.value.type.enum_def
+ ? namer_.Namespace(*field.value.type.enum_def->defined_namespace)
+ : "";
- if (field_ns_str != "" && field_ns_str != curr_ns_str) {
- return ImportAliasName(field_ns_str) + "." + type_name;
+ if (field_namespace != "" && field_namespace != current_namespace) {
+ return ImportAliasName(field_namespace) + "." + type_name;
} else {
return type_name;
}
@@ -442,29 +404,29 @@
// Generate an accessor struct with constructor for a flatbuffers struct.
void GenStruct(const StructDef &struct_def,
- namespace_code_map *namespace_code) {
+ namespace_code_map &namespace_code) {
if (struct_def.generated) return;
- auto object_namespace = BuildNamespaceName(*struct_def.defined_namespace);
- std::string code;
+ std::string &code =
+ namespace_code[namer_.Namespace(*struct_def.defined_namespace)];
- const auto &object_name = struct_def.name;
+ const auto &struct_type = namer_.Type(struct_def);
// Emit constructor
- GenDocComment(struct_def.doc_comment, &code, "");
+ GenDocComment(struct_def.doc_comment, "", code);
- auto reader_name = "_" + object_name + "Reader";
- auto builder_name = object_name + "Builder";
- auto object_builder_name = object_name + "ObjectBuilder";
+ auto reader_name = "_" + struct_type + "Reader";
+ auto builder_name = struct_type + "Builder";
+ auto object_builder_name = struct_type + "ObjectBuilder";
std::string reader_code, builder_code;
- code += "class " + object_name + " {\n";
+ code += "class " + struct_type + " {\n";
- code += " " + object_name + "._(this._bc, this._bcOffset);\n";
+ code += " " + struct_type + "._(this._bc, this._bcOffset);\n";
if (!struct_def.fixed) {
- code += " factory " + object_name + "(List<int> bytes) {\n";
+ code += " factory " + struct_type + "(List<int> bytes) {\n";
code +=
" final rootRef = " + _kFb + ".BufferContext.fromBytes(bytes);\n";
code += " return reader.read(rootRef, 0);\n";
@@ -472,7 +434,7 @@
}
code += "\n";
- code += " static const " + _kFb + ".Reader<" + object_name +
+ code += " static const " + _kFb + ".Reader<" + struct_type +
"> reader = " + reader_name + "();\n\n";
code += " final " + _kFb + ".BufferContext _bc;\n";
@@ -481,20 +443,20 @@
std::vector<std::pair<int, FieldDef *>> non_deprecated_fields;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ FieldDef &field = **it;
if (field.deprecated) continue;
auto offset = static_cast<int>(it - struct_def.fields.vec.begin());
non_deprecated_fields.push_back(std::make_pair(offset, &field));
}
- GenImplementationGetters(struct_def, non_deprecated_fields, &code);
+ GenImplementationGetters(struct_def, non_deprecated_fields, code);
if (parser_.opts.generate_object_based_api) {
code +=
"\n" + GenStructObjectAPIUnpack(struct_def, non_deprecated_fields);
- code += "\n static int pack(fb.Builder fbBuilder, " + struct_def.name +
- "T? object) {\n";
+ code += "\n static int pack(fb.Builder fbBuilder, " +
+ namer_.ObjectType(struct_def) + "? object) {\n";
code += " if (object == null) return 0;\n";
code += " return object.pack(fbBuilder);\n";
code += " }\n";
@@ -506,15 +468,13 @@
code += GenStructObjectAPI(struct_def, non_deprecated_fields);
}
- GenReader(struct_def, &reader_name, &reader_code);
- GenBuilder(struct_def, non_deprecated_fields, &builder_name, &builder_code);
- GenObjectBuilder(struct_def, non_deprecated_fields, &object_builder_name,
- &builder_code);
+ GenReader(struct_def, reader_name, reader_code);
+ GenBuilder(struct_def, non_deprecated_fields, builder_name, builder_code);
+ GenObjectBuilder(struct_def, non_deprecated_fields, object_builder_name,
+ builder_code);
code += reader_code;
code += builder_code;
-
- (*namespace_code)[object_namespace] += code;
}
// Generate an accessor struct with constructor for a flatbuffers struct.
@@ -522,23 +482,23 @@
const StructDef &struct_def,
const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields) {
std::string code;
- GenDocComment(struct_def.doc_comment, &code, "");
+ GenDocComment(struct_def.doc_comment, "", code);
- std::string class_name = struct_def.name + "T";
- code += "class " + class_name + " implements " + _kFb + ".Packable {\n";
+ std::string object_type = namer_.ObjectType(struct_def);
+ code += "class " + object_type + " implements " + _kFb + ".Packable {\n";
std::string constructor_args;
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
const FieldDef &field = *it->second;
- std::string field_name = ConvertCase(field.name, Case::kLowerCamel);
- std::string defaultValue = getDefaultValue(field.value);
- std::string type_name =
+ const std::string field_name = namer_.Field(field);
+ const std::string defaultValue = getDefaultValue(field.value);
+ const std::string type_name =
GenDartTypeName(field.value.type, struct_def.defined_namespace, field,
defaultValue.empty() && !struct_def.fixed, "T");
- GenDocComment(field.doc_comment, &code, "", " ");
+ GenDocComment(field.doc_comment, " ", code);
code += " " + type_name + " " + field_name + ";\n";
if (!constructor_args.empty()) constructor_args += ",\n";
@@ -549,10 +509,10 @@
if (IsEnum(field.value.type)) {
auto &enum_def = *field.value.type.enum_def;
if (auto val = enum_def.FindByValue(defaultValue)) {
- constructor_args += " = " + enum_def.name + "." + val->name;
+ constructor_args += " = " + namer_.EnumVariant(enum_def, *val);
} else {
- constructor_args +=
- " = const " + enum_def.name + "._(" + defaultValue + ")";
+ constructor_args += " = const " + namer_.Type(enum_def) + "._(" +
+ defaultValue + ")";
}
} else {
constructor_args += " = " + defaultValue;
@@ -561,12 +521,12 @@
}
if (!constructor_args.empty()) {
- code += "\n " + class_name + "({\n" + constructor_args + "});\n\n";
+ code += "\n " + object_type + "({\n" + constructor_args + "});\n\n";
}
code += GenStructObjectAPIPack(struct_def, non_deprecated_fields);
code += "\n";
- code += GenToString(class_name, non_deprecated_fields);
+ code += GenToString(object_type, non_deprecated_fields);
code += "}\n\n";
return code;
@@ -581,7 +541,7 @@
it != non_deprecated_fields.end(); ++it) {
const FieldDef &field = *it->second;
- std::string field_name = ConvertCase(field.name, Case::kLowerCamel);
+ const std::string field_name = namer_.Field(field);
if (!constructor_args.empty()) constructor_args += ",\n";
constructor_args += " " + field_name + ": ";
@@ -612,8 +572,8 @@
}
}
- std::string class_name = struct_def.name + "T";
- std::string code = " " + class_name + " unpack() => " + class_name + "(";
+ const std::string object_type = namer_.ObjectType(struct_def);
+ std::string code = " " + object_type + " unpack() => " + object_type + "(";
if (!constructor_args.empty()) code += "\n" + constructor_args;
code += ");\n";
return code;
@@ -640,7 +600,7 @@
if (std::equal(root_namespace->components.begin(),
root_namespace->components.end(),
qualified_name_parts.begin())) {
- return type.struct_def->name;
+ return namer_.Type(*type.struct_def);
}
std::string ns;
@@ -660,39 +620,35 @@
if (it != qualified_name_parts.end() - 1) { ns += "_"; }
}
- return ns + "." + type.struct_def->name;
+ return ns + "." + namer_.Type(*type.struct_def);
}
void GenImplementationGetters(
const StructDef &struct_def,
- std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
- std::string *code_ptr) {
- auto &code = *code_ptr;
-
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ std::string &code) {
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
- std::string field_name = ConvertCase(field.name, Case::kLowerCamel);
- std::string defaultValue = getDefaultValue(field.value);
- bool isNullable = defaultValue.empty() && !struct_def.fixed;
- std::string type_name =
+ const std::string field_name = namer_.Field(field);
+ const std::string defaultValue = getDefaultValue(field.value);
+ const bool isNullable = defaultValue.empty() && !struct_def.fixed;
+ const std::string type_name =
GenDartTypeName(field.value.type, struct_def.defined_namespace, field,
isNullable, "");
- GenDocComment(field.doc_comment, &code, "", " ");
+ GenDocComment(field.doc_comment, " ", code);
code += " " + type_name + " get " + field_name;
if (field.value.type.base_type == BASE_TYPE_UNION) {
code += " {\n";
code += " switch (" + field_name + "Type?.value) {\n";
- auto &enum_def = *field.value.type.enum_def;
+ const auto &enum_def = *field.value.type.enum_def;
for (auto en_it = enum_def.Vals().begin() + 1;
en_it != enum_def.Vals().end(); ++en_it) {
- auto &ev = **en_it;
-
- auto enum_name = NamespaceAliasFromUnionType(
+ const auto &ev = **en_it;
+ const auto enum_name = NamespaceAliasFromUnionType(
enum_def.defined_namespace, ev.union_type);
code += " case " + enum_def.ToString(ev) + ": return " +
enum_name + ".reader.vTableGetNullable(_bc, _bcOffset, " +
@@ -733,7 +689,7 @@
}
code += "\n";
- code += GenToString(struct_def.name, non_deprecated_fields);
+ code += GenToString(namer_.Type(struct_def), non_deprecated_fields);
}
std::string GenToString(
@@ -745,10 +701,15 @@
code += " return '" + object_name + "{";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
- code += ConvertCase(field.name, Case::kLowerCamel) + ": $" +
- ConvertCase(field.name, Case::kLowerCamel);
+ const std::string field = namer_.Field(*it->second);
+ // We need to escape the fact that some fields have $ in the name which is
+ // also used in symbol/string substitution.
+ std::string escaped_field;
+ for (size_t i = 0; i < field.size(); i++) {
+ if (field[i] == '$') escaped_field.push_back('\\');
+ escaped_field.push_back(field[i]);
+ }
+ code += escaped_field + ": ${" + field + "}";
if (it != non_deprecated_fields.end() - 1) { code += ", "; }
}
code += "}';\n";
@@ -779,11 +740,9 @@
}
}
- void GenReader(const StructDef &struct_def, std::string *reader_name_ptr,
- std::string *code_ptr) {
- auto &code = *code_ptr;
- auto &reader_name = *reader_name_ptr;
- auto &impl_name = struct_def.name;
+ void GenReader(const StructDef &struct_def, const std::string &reader_name,
+ std::string &code) {
+ const auto struct_type = namer_.Type(struct_def);
code += "class " + reader_name + " extends " + _kFb;
if (struct_def.fixed) {
@@ -791,7 +750,7 @@
} else {
code += ".TableReader<";
}
- code += impl_name + "> {\n";
+ code += struct_type + "> {\n";
code += " const " + reader_name + "();\n\n";
if (struct_def.fixed) {
@@ -799,27 +758,26 @@
code += " int get size => " + NumToString(struct_def.bytesize) + ";\n\n";
}
code += " @override\n";
- code += " " + impl_name +
+ code += " " + struct_type +
" createObject(fb.BufferContext bc, int offset) => \n " +
- impl_name + "._(bc, offset);\n";
+ struct_type + "._(bc, offset);\n";
code += "}\n\n";
}
- void GenBuilder(const StructDef &struct_def,
- std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
- std::string *builder_name_ptr, std::string *code_ptr) {
+ void GenBuilder(
+ const StructDef &struct_def,
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ const std::string &builder_name, std::string &code) {
if (non_deprecated_fields.size() == 0) { return; }
- auto &code = *code_ptr;
- auto &builder_name = *builder_name_ptr;
code += "class " + builder_name + " {\n";
code += " " + builder_name + "(this.fbBuilder);\n\n";
code += " final " + _kFb + ".Builder fbBuilder;\n\n";
if (struct_def.fixed) {
- StructBuilderBody(struct_def, non_deprecated_fields, code_ptr);
+ StructBuilderBody(struct_def, non_deprecated_fields, code);
} else {
- TableBuilderBody(struct_def, non_deprecated_fields, code_ptr);
+ TableBuilderBody(struct_def, non_deprecated_fields, code);
}
code += "}\n\n";
@@ -827,15 +785,13 @@
void StructBuilderBody(
const StructDef &struct_def,
- std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
- std::string *code_ptr) {
- auto &code = *code_ptr;
-
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ std::string &code) {
code += " int finish(";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
+ const std::string field_name = namer_.Field(field);
if (IsStruct(field.value.type)) {
code += "fb.StructBuilder";
@@ -843,25 +799,25 @@
code += GenDartTypeName(field.value.type, struct_def.defined_namespace,
field);
}
- code += " " + field.name;
+ code += " " + field_name;
if (it != non_deprecated_fields.end() - 1) { code += ", "; }
}
code += ") {\n";
for (auto it = non_deprecated_fields.rbegin();
it != non_deprecated_fields.rend(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
+ const std::string field_name = namer_.Field(field);
if (field.padding) {
code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
}
if (IsStruct(field.value.type)) {
- code += " " + field.name + "();\n";
+ code += " " + field_name + "();\n";
} else {
code += " fbBuilder.put" + GenType(field.value.type) + "(";
- code += field.name;
+ code += field_name;
if (field.value.type.enum_def) { code += ".value"; }
code += ");\n";
}
@@ -872,10 +828,8 @@
void TableBuilderBody(
const StructDef &struct_def,
- std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
- std::string *code_ptr) {
- auto &code = *code_ptr;
-
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ std::string &code) {
code += " void begin() {\n";
code += " fbBuilder.startTable(" +
NumToString(struct_def.fields.vec.size()) + ");\n";
@@ -883,28 +837,27 @@
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
- auto offset = pair.first;
+ const auto &field = *it->second;
+ const auto offset = it->first;
+ const std::string add_field = namer_.Method("add", field);
+ const std::string field_var = namer_.Variable(field);
if (IsScalar(field.value.type.base_type)) {
- code += " int add" + ConvertCase(field.name, Case::kUpperCamel) + "(";
+ code += " int " + add_field + "(";
code += GenDartTypeName(field.value.type, struct_def.defined_namespace,
field);
- code += "? " + ConvertCase(field.name, Case::kLowerCamel) + ") {\n";
+ code += "? " + field_var + ") {\n";
code += " fbBuilder.add" + GenType(field.value.type) + "(" +
NumToString(offset) + ", ";
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += field_var;
if (field.value.type.enum_def) { code += "?.value"; }
code += ");\n";
} else if (IsStruct(field.value.type)) {
- code += " int add" + ConvertCase(field.name, Case::kUpperCamel) +
- "(int offset) {\n";
+ code += " int " + add_field + "(int offset) {\n";
code +=
" fbBuilder.addStruct(" + NumToString(offset) + ", offset);\n";
} else {
- code += " int add" + ConvertCase(field.name, Case::kUpperCamel) +
- "Offset(int? offset) {\n";
+ code += " int " + add_field + "Offset(int? offset) {\n";
code +=
" fbBuilder.addOffset(" + NumToString(offset) + ", offset);\n";
}
@@ -920,21 +873,17 @@
void GenObjectBuilder(
const StructDef &struct_def,
- std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
- std::string *builder_name_ptr, std::string *code_ptr) {
- auto &code = *code_ptr;
- auto &builder_name = *builder_name_ptr;
-
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ const std::string &builder_name, std::string &code) {
code += "class " + builder_name + " extends " + _kFb + ".ObjectBuilder {\n";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
code += " final " +
GenDartTypeName(field.value.type, struct_def.defined_namespace,
field, !struct_def.fixed, "ObjectBuilder") +
- " _" + ConvertCase(field.name, Case::kLowerCamel) + ";\n";
+ " _" + namer_.Variable(field) + ";\n";
}
code += "\n";
code += " " + builder_name + "(";
@@ -943,24 +892,21 @@
code += "{\n";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
code += " ";
code += (struct_def.fixed ? "required " : "") +
GenDartTypeName(field.value.type, struct_def.defined_namespace,
field, !struct_def.fixed, "ObjectBuilder") +
- " " + ConvertCase(field.name, Case::kLowerCamel) + ",\n";
+ " " + namer_.Variable(field) + ",\n";
}
code += " })\n";
code += " : ";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
- code += "_" + ConvertCase(field.name, Case::kLowerCamel) + " = " +
- ConvertCase(field.name, Case::kLowerCamel);
+ code += "_" + namer_.Variable(field) + " = " + namer_.Variable(field);
if (it == non_deprecated_fields.end() - 1) {
code += ";\n\n";
} else {
@@ -1000,11 +946,9 @@
if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type))
continue;
- std::string offset_name =
- ConvertCase(field.name, Case::kLowerCamel) + "Offset";
- std::string field_name = (prependUnderscore ? "_" : "") +
- ConvertCase(field.name, Case::kLowerCamel);
-
+ std::string offset_name = namer_.Variable(field) + "Offset";
+ std::string field_name =
+ (prependUnderscore ? "_" : "") + namer_.Variable(field);
// custom handling for fixed-sized struct in pack()
if (pack && IsVector(field.value.type) &&
field.value.type.VectorType().base_type == BASE_TYPE_STRUCT &&
@@ -1013,7 +957,7 @@
code += " if (" + field_name + " != null) {\n";
code +=
" for (var e in " + field_name + "!) { e.pack(fbBuilder); }\n";
- code += " " + ConvertCase(field.name, Case::kLowerCamel) +
+ code += " " + namer_.Variable(field) +
"Offset = fbBuilder.endStructVector(" + field_name +
"!.length);\n";
code += " }\n";
@@ -1072,8 +1016,8 @@
for (auto it = non_deprecated_fields.rbegin();
it != non_deprecated_fields.rend(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
+ const std::string field_name = namer_.Field(field);
if (field.padding) {
code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
@@ -1082,11 +1026,11 @@
if (IsStruct(field.value.type)) {
code += " ";
if (prependUnderscore) { code += "_"; }
- code += field.name + (pack ? ".pack" : ".finish") + "(fbBuilder);\n";
+ code += field_name + (pack ? ".pack" : ".finish") + "(fbBuilder);\n";
} else {
code += " fbBuilder.put" + GenType(field.value.type) + "(";
if (prependUnderscore) { code += "_"; }
- code += field.name;
+ code += field_name;
if (field.value.type.enum_def) { code += ".value"; }
code += ");\n";
}
@@ -1106,34 +1050,35 @@
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
- auto offset = pair.first;
+ const FieldDef &field = *it->second;
+ auto offset = it->first;
- std::string field_name = (prependUnderscore ? "_" : "") +
- ConvertCase(field.name, Case::kLowerCamel);
+ std::string field_var =
+ (prependUnderscore ? "_" : "") + namer_.Variable(field);
if (IsScalar(field.value.type.base_type)) {
code += " fbBuilder.add" + GenType(field.value.type) + "(" +
- NumToString(offset) + ", " + field_name;
+ NumToString(offset) + ", " + field_var;
if (field.value.type.enum_def) {
bool isNullable = getDefaultValue(field.value).empty();
code += (isNullable || !pack) ? "?.value" : ".value";
}
code += ");\n";
} else if (IsStruct(field.value.type)) {
- code += " if (" + field_name + " != null) {\n";
+ code += " if (" + field_var + " != null) {\n";
code += " fbBuilder.addStruct(" + NumToString(offset) + ", " +
- field_name + (pack ? "!.pack" : "!.finish") + "(fbBuilder));\n";
+ field_var + (pack ? "!.pack" : "!.finish") + "(fbBuilder));\n";
code += " }\n";
} else {
code += " fbBuilder.addOffset(" + NumToString(offset) + ", " +
- ConvertCase(field.name, Case::kLowerCamel) + "Offset);\n";
+ namer_.Variable(field) + "Offset);\n";
}
}
code += " return fbBuilder.endTable();\n";
return code;
}
+
+ const IdlNamer namer_;
};
} // namespace dart
@@ -1148,8 +1093,7 @@
auto filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
dart::DartGenerator generator(parser, path, file_name);
- auto make_rule =
- generator.GeneratedFileName(path, file_name, parser.opts) + ": ";
+ auto make_rule = generator.Filename("") + ": ";
auto included_files = parser.GetIncludedFilesRecursive(file_name);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
diff --git a/third_party/flatbuffers/src/idl_gen_fbs.cpp b/third_party/flatbuffers/src/idl_gen_fbs.cpp
index 35c1a7d..782557f 100644
--- a/third_party/flatbuffers/src/idl_gen_fbs.cpp
+++ b/third_party/flatbuffers/src/idl_gen_fbs.cpp
@@ -82,7 +82,7 @@
if (it->second.empty())
continue;
std::string basename;
- if(parser.opts.keep_include_path) {
+ if(parser.opts.keep_prefix) {
basename = flatbuffers::StripExtension(it->second);
} else {
basename = flatbuffers::StripPath(
diff --git a/third_party/flatbuffers/src/idl_gen_go.cpp b/third_party/flatbuffers/src/idl_gen_go.cpp
index 306a022..51e018a 100644
--- a/third_party/flatbuffers/src/idl_gen_go.cpp
+++ b/third_party/flatbuffers/src/idl_gen_go.cpp
@@ -23,7 +23,7 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
-#include "namer.h"
+#include "idl_namer.h"
#ifdef _WIN32
# include <direct.h>
@@ -38,8 +38,10 @@
namespace go {
+namespace {
+
// see https://golang.org/ref/spec#Keywords
-std::set<std::string> GoKeywords() {
+static std::set<std::string> GoKeywords() {
return {
"break", "default", "func", "interface", "select",
"case", "defer", "go", "map", "struct",
@@ -49,7 +51,7 @@
};
}
-Namer::Config GoDefaultConfig() {
+static Namer::Config GoDefaultConfig() {
// Note that the functions with user defined types in the name use
// upper camel case for all but the user defined type itself, which is keep
// cased. Despite being a function, we interpret it as a Type.
@@ -61,6 +63,7 @@
/*variables=*/Case::kLowerCamel,
/*variants=*/Case::kKeep,
/*enum_variant_seperator=*/"", // I.e. Concatenate.
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
/*namespaces=*/Case::kKeep,
/*namespace_seperator=*/"__",
/*object_prefix=*/"",
@@ -74,6 +77,8 @@
/*filename_extension=*/".go" };
}
+} // namespace
+
class GoGenerator : public BaseGenerator {
public:
GoGenerator(const Parser &parser, const std::string &path,
@@ -81,8 +86,8 @@
: BaseGenerator(parser, path, file_name, "" /* not used*/,
"" /* not used */, "go"),
cur_name_space_(nullptr),
- namer_({ GoDefaultConfig().WithFlagOptions(parser.opts, path),
- GoKeywords() }) {
+ namer_(WithFlagOptions(GoDefaultConfig(), parser.opts, path),
+ GoKeywords()) {
std::istringstream iss(go_namespace);
std::string component;
while (std::getline(iss, component, '.')) {
@@ -140,7 +145,7 @@
private:
Namespace go_namespace_;
Namespace *cur_name_space_;
- const Namer namer_;
+ const IdlNamer namer_;
struct NamespacePtrLess {
bool operator()(const Namespace *a, const Namespace *b) const {
@@ -160,7 +165,7 @@
void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
- code += "type " + namer_.Type(struct_def.name) + " struct {\n\t";
+ code += "type " + namer_.Type(struct_def) + " struct {\n\t";
// _ is reserved in flatbuffers field names, so no chance of name conflict:
code += "_tab ";
@@ -171,7 +176,7 @@
// Construct the name of the type for this enum.
std::string GetEnumTypeName(const EnumDef &enum_def) {
return WrapInNameSpaceAndTrack(enum_def.defined_namespace,
- namer_.Type(enum_def.name));
+ namer_.Type(enum_def));
}
// Create a type for the enum values.
@@ -192,7 +197,7 @@
size_t max_name_length, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "\t";
- code += namer_.EnumVariant(enum_def.name, ev.name);
+ code += namer_.EnumVariant(enum_def, ev);
code += " ";
code += std::string(max_name_length - ev.name.length(), ' ');
code += GetEnumTypeName(enum_def);
@@ -219,7 +224,7 @@
size_t max_name_length, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "\t";
- code += namer_.EnumVariant(enum_def.name, ev.name);
+ code += namer_.EnumVariant(enum_def, ev);
code += ": ";
code += std::string(max_name_length - ev.name.length(), ' ');
code += "\"";
@@ -236,7 +241,7 @@
// Generate String() method on enum type.
void EnumStringer(const EnumDef &enum_def, std::string *code_ptr) {
std::string &code = *code_ptr;
- const std::string enum_type = namer_.Type(enum_def.name);
+ const std::string enum_type = namer_.Type(enum_def);
code += "func (v " + enum_type + ") String() string {\n";
code += "\tif s, ok := EnumNames" + enum_type + "[v]; ok {\n";
code += "\t\treturn s\n";
@@ -250,7 +255,7 @@
void BeginEnumValues(const EnumDef &enum_def, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "var EnumValues";
- code += namer_.Type(enum_def.name);
+ code += namer_.Type(enum_def);
code += " = map[string]" + GetEnumTypeName(enum_def) + "{\n";
}
@@ -262,7 +267,7 @@
code += ev.name;
code += "\": ";
code += std::string(max_name_length - ev.name.length(), ' ');
- code += namer_.EnumVariant(enum_def.name, ev.name);
+ code += namer_.EnumVariant(enum_def, ev);
code += ",\n";
}
@@ -277,7 +282,7 @@
std::string *code_ptr) {
std::string &code = *code_ptr;
const std::string size_prefix[] = { "", "SizePrefixed" };
- const std::string struct_type = namer_.Type(struct_def.name);
+ const std::string struct_type = namer_.Type(struct_def);
for (int i = 0; i < 2; i++) {
code += "func Get" + size_prefix[i] + "RootAs" + struct_type;
@@ -336,7 +341,7 @@
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name) + "Length(";
+ code += " " + namer_.Function(field) + "Length(";
code += ") int " + OffsetPrefix(field);
code += "\t\treturn rcv._tab.VectorLen(o)\n\t}\n";
code += "\treturn 0\n}\n\n";
@@ -348,7 +353,7 @@
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name) + "Bytes(";
+ code += " " + namer_.Function(field) + "Bytes(";
code += ") []byte " + OffsetPrefix(field);
code += "\t\treturn rcv._tab.ByteVector(o + rcv._tab.Pos)\n\t}\n";
code += "\treturn nil\n}\n\n";
@@ -360,7 +365,7 @@
std::string &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name);
+ code += " " + namer_.Function(field);
code += "() " + TypeName(field) + " {\n";
code += "\treturn " +
CastToEnum(field.value.type,
@@ -375,7 +380,7 @@
std::string &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name);
+ code += " " + namer_.Function(field);
code += "() " + TypeName(field) + " ";
code += OffsetPrefix(field);
if (field.IsScalarOptional()) {
@@ -384,9 +389,7 @@
code += "\t\treturn ";
}
code += CastToEnum(field.value.type, getter + "(o + rcv._tab.Pos)");
- if (field.IsScalarOptional()) {
- code += "\n\t\treturn &v";
- }
+ if (field.IsScalarOptional()) { code += "\n\t\treturn &v"; }
code += "\n\t}\n";
code += "\treturn " + GenConstant(field) + "\n";
code += "}\n\n";
@@ -398,7 +401,7 @@
const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name);
+ code += " " + namer_.Function(field);
code += "(obj *" + TypeName(field);
code += ") *" + TypeName(field);
code += " {\n";
@@ -417,7 +420,7 @@
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name);
+ code += " " + namer_.Function(field);
code += "(obj *";
code += TypeName(field);
code += ") *" + TypeName(field) + " " + OffsetPrefix(field);
@@ -439,7 +442,7 @@
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name);
+ code += " " + namer_.Function(field);
code += "() " + TypeName(field) + " ";
code += OffsetPrefix(field) + "\t\treturn " + GenGetter(field.value.type);
code += "(o + rcv._tab.Pos)\n\t}\n\treturn nil\n";
@@ -451,7 +454,7 @@
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name) + "(";
+ code += " " + namer_.Function(field) + "(";
code += "obj " + GenTypePointer(field.value.type) + ") bool ";
code += OffsetPrefix(field);
code += "\t\t" + GenGetter(field.value.type);
@@ -467,7 +470,7 @@
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name);
+ code += " " + namer_.Function(field);
code += "(obj *" + TypeName(field);
code += ", j int) bool " + OffsetPrefix(field);
code += "\t\tx := rcv._tab.Vector(o)\n";
@@ -490,7 +493,7 @@
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += " " + namer_.Function(field.name);
+ code += " " + namer_.Function(field);
code += "(j int) " + TypeName(field) + " ";
code += OffsetPrefix(field);
code += "\t\ta := rcv._tab.Vector(o)\n";
@@ -538,7 +541,7 @@
} else {
std::string &code = *code_ptr;
code += std::string(", ") + nameprefix;
- code += namer_.Variable(field.name);
+ code += namer_.Variable(field);
code += " " + TypeName(field);
}
}
@@ -568,7 +571,7 @@
} else {
code += "\tbuilder.Prepend" + GenMethod(field) + "(";
code += CastToBaseType(field.value.type,
- nameprefix + namer_.Variable(field.name)) +
+ nameprefix + namer_.Variable(field)) +
")\n";
}
}
@@ -583,7 +586,7 @@
// 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 += "func " + namer_.Type(struct_def.name) + "Start";
+ code += "func " + namer_.Type(struct_def) + "Start";
code += "(builder *flatbuffers.Builder) {\n";
code += "\tbuilder.StartObject(";
code += NumToString(struct_def.fields.vec.size());
@@ -594,9 +597,8 @@
void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
const size_t offset, std::string *code_ptr) {
std::string &code = *code_ptr;
- const std::string field_var = namer_.Variable(field.name);
- code += "func " + namer_.Type(struct_def.name) + "Add" +
- namer_.Function(field.name);
+ const std::string field_var = namer_.Variable(field);
+ code += "func " + namer_.Type(struct_def) + "Add" + namer_.Function(field);
code += "(builder *flatbuffers.Builder, ";
code += field_var + " ";
if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
@@ -632,8 +634,8 @@
void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;
- code += "func " + namer_.Type(struct_def.name) + "Start";
- code += namer_.Function(field.name);
+ code += "func " + namer_.Type(struct_def) + "Start";
+ code += namer_.Function(field);
code += "Vector(builder *flatbuffers.Builder, numElems int) ";
code += "flatbuffers.UOffsetT {\n\treturn builder.StartVector(";
auto vector_type = field.value.type.VectorType();
@@ -647,7 +649,7 @@
// 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 += "func " + namer_.Type(struct_def.name) + "End";
+ code += "func " + namer_.Type(struct_def) + "End";
code += "(builder *flatbuffers.Builder) flatbuffers.UOffsetT ";
code += "{\n\treturn builder.EndObject()\n}\n";
}
@@ -655,7 +657,7 @@
// Generate the receiver for function signatures.
void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
- code += "func (rcv *" + namer_.Type(struct_def.name) + ")";
+ code += "func (rcv *" + namer_.Type(struct_def) + ")";
}
// Generate a struct field getter, conditioned on its child type(s).
@@ -708,8 +710,9 @@
std::string setter =
"rcv._tab.Mutate" + namer_.Method(GenTypeBasic(field.value.type));
GenReceiver(struct_def, code_ptr);
- code += " Mutate" + namer_.Function(field.name);
- code += "(n " + GenTypeGet(field.value.type) + ") bool {\n\treturn " + setter;
+ code += " Mutate" + namer_.Function(field);
+ code +=
+ "(n " + GenTypeGet(field.value.type) + ") bool {\n\treturn " + setter;
code += "(rcv._tab.Pos+flatbuffers.UOffsetT(";
code += NumToString(field.value.offset) + "), ";
code += CastToBaseType(field.value.type, "n") + ")\n}\n\n";
@@ -722,7 +725,7 @@
std::string setter = "rcv._tab.Mutate" +
namer_.Method(GenTypeBasic(field.value.type)) + "Slot";
GenReceiver(struct_def, code_ptr);
- code += " Mutate" + namer_.Function(field.name);
+ code += " Mutate" + namer_.Function(field);
code += "(n " + GenTypeGet(field.value.type) + ") bool {\n\treturn ";
code += setter + "(" + NumToString(field.value.offset) + ", ";
code += CastToBaseType(field.value.type, "n") + ")\n";
@@ -738,7 +741,7 @@
std::string setter =
"rcv._tab.Mutate" + namer_.Method(GenTypeBasic(vectortype));
GenReceiver(struct_def, code_ptr);
- code += " Mutate" + namer_.Function(field.name);
+ code += " Mutate" + namer_.Function(field);
code += "(j int, n " + TypeName(field) + ") bool ";
code += OffsetPrefix(field);
code += "\t\ta := rcv._tab.Vector(o)\n";
@@ -841,11 +844,10 @@
field.value.type.enum_def != nullptr &&
field.value.type.enum_def->is_union)
continue;
- code += "\t" + namer_.Field(field.name) + " ";
- if (field.IsScalarOptional()) {
- code += "*";
- }
- code += NativeType(field.value.type) + "\n";
+ code += "\t" + namer_.Field(field) + " ";
+ if (field.IsScalarOptional()) { code += "*"; }
+ code += NativeType(field.value.type) + " `json:\"" + field.name + "\"`" +
+ "\n";
}
code += "}\n\n";
@@ -861,7 +863,7 @@
void GenNativeUnion(const EnumDef &enum_def, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "type " + NativeName(enum_def) + " struct {\n";
- code += "\tType " + namer_.Type(enum_def.name) + "\n";
+ code += "\tType " + namer_.Type(enum_def) + "\n";
code += "\tValue interface{}\n";
code += "}\n\n";
}
@@ -877,7 +879,7 @@
++it2) {
const EnumVal &ev = **it2;
if (ev.IsZero()) continue;
- code += "\tcase " + namer_.EnumVariant(enum_def.name, ev.name) + ":\n";
+ code += "\tcase " + namer_.EnumVariant(enum_def, ev) + ":\n";
code += "\t\treturn t.Value.(" + NativeType(ev.union_type) +
").Pack(builder)\n";
}
@@ -889,7 +891,7 @@
void GenNativeUnionUnPack(const EnumDef &enum_def, std::string *code_ptr) {
std::string &code = *code_ptr;
- code += "func (rcv " + namer_.Type(enum_def.name) +
+ code += "func (rcv " + namer_.Type(enum_def) +
") UnPack(table flatbuffers.Table) *" + NativeName(enum_def) +
" {\n";
code += "\tswitch rcv {\n";
@@ -898,13 +900,13 @@
++it2) {
const EnumVal &ev = **it2;
if (ev.IsZero()) continue;
- code += "\tcase " + namer_.EnumVariant(enum_def.name, ev.name) + ":\n";
+ code += "\tcase " + namer_.EnumVariant(enum_def, ev) + ":\n";
code += "\t\tx := " + ev.union_type.struct_def->name + "{_tab: table}\n";
code += "\t\treturn &" +
WrapInNameSpaceAndTrack(enum_def.defined_namespace,
NativeName(enum_def)) +
- "{ Type: " + namer_.EnumVariant(enum_def.name, ev.name) +
+ "{ Type: " + namer_.EnumVariant(enum_def, ev) +
", Value: x.UnPack() }\n";
}
code += "\t}\n";
@@ -914,7 +916,7 @@
void GenNativeTablePack(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
- const std::string struct_type = namer_.Type(struct_def.name);
+ const std::string struct_type = namer_.Type(struct_def);
code += "func (t *" + NativeName(struct_def) +
") Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {\n";
@@ -925,8 +927,8 @@
if (field.deprecated) continue;
if (IsScalar(field.value.type.base_type)) continue;
- const std::string field_field = namer_.Field(field.name);
- const std::string field_var = namer_.Variable(field.name);
+ const std::string field_field = namer_.Field(field);
+ const std::string field_var = namer_.Variable(field);
const std::string offset = field_var + "Offset";
if (IsString(field.value.type)) {
@@ -962,7 +964,7 @@
"[j].Pack(builder)\n";
code += "\t\t}\n";
}
- code += "\t\t" + struct_type + "Start" + namer_.Function(field.name) +
+ code += "\t\t" + struct_type + "Start" + namer_.Function(field) +
"Vector(builder, " + length + ")\n";
code += "\t\tfor j := " + length + " - 1; j >= 0; j-- {\n";
if (IsScalar(field.value.type.element)) {
@@ -996,9 +998,9 @@
it != struct_def.fields.vec.end(); ++it) {
const FieldDef &field = **it;
if (field.deprecated) continue;
- const std::string field_field = namer_.Field(field.name);
- const std::string field_fn = namer_.Function(field.name);
- const std::string offset = namer_.Variable(field.name) + "Offset";
+ const std::string field_field = namer_.Field(field);
+ const std::string field_fn = namer_.Function(field);
+ const std::string offset = namer_.Variable(field) + "Offset";
if (IsScalar(field.value.type.base_type)) {
std::string prefix;
@@ -1011,9 +1013,7 @@
code += "\t" + struct_type + "Add" + field_fn + "(builder, " +
prefix + "t." + field_field + ")\n";
}
- if (field.IsScalarOptional()) {
- code += "\t}\n";
- }
+ if (field.IsScalarOptional()) { code += "\t}\n"; }
} else {
if (field.value.type.base_type == BASE_TYPE_STRUCT &&
field.value.type.struct_def->fixed) {
@@ -1037,7 +1037,7 @@
void GenNativeTableUnPack(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
- const std::string struct_type = namer_.Type(struct_def.name);
+ const std::string struct_type = namer_.Type(struct_def);
code += "func (rcv *" + struct_type + ") UnPackTo(t *" +
NativeName(struct_def) + ") {\n";
@@ -1045,8 +1045,8 @@
it != struct_def.fields.vec.end(); ++it) {
const FieldDef &field = **it;
if (field.deprecated) continue;
- const std::string field_field = namer_.Field(field.name);
- const std::string field_var = namer_.Variable(field.name);
+ const std::string field_field = namer_.Field(field);
+ const std::string field_var = namer_.Variable(field);
const std::string length = field_var + "Length";
if (IsScalar(field.value.type.base_type)) {
if (field.value.type.enum_def != nullptr &&
@@ -1089,8 +1089,8 @@
} else if (field.value.type.base_type == BASE_TYPE_UNION) {
const std::string field_table = field_var + "Table";
code += "\t" + field_table + " := flatbuffers.Table{}\n";
- code += "\tif rcv." + namer_.Method(field.name) + "(&" + field_table +
- ") {\n";
+ code +=
+ "\tif rcv." + namer_.Method(field) + "(&" + field_table + ") {\n";
code += "\t\tt." + field_field + " = rcv." +
namer_.Method(field.name + UnionTypeFieldSuffix()) +
"().UnPack(" + field_table + ")\n";
@@ -1116,7 +1116,7 @@
code += "func (t *" + NativeName(struct_def) +
") Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {\n";
code += "\tif t == nil { return 0 }\n";
- code += "\treturn Create" + namer_.Type(struct_def.name) + "(builder";
+ code += "\treturn Create" + namer_.Type(struct_def) + "(builder";
StructPackArgs(struct_def, "", code_ptr);
code += ")\n";
code += "}\n";
@@ -1130,10 +1130,10 @@
const FieldDef &field = **it;
if (field.value.type.base_type == BASE_TYPE_STRUCT) {
StructPackArgs(*field.value.type.struct_def,
- (nameprefix + namer_.Field(field.name) + ".").c_str(),
+ (nameprefix + namer_.Field(field) + ".").c_str(),
code_ptr);
} else {
- code += std::string(", t.") + nameprefix + namer_.Field(field.name);
+ code += std::string(", t.") + nameprefix + namer_.Field(field);
}
}
}
@@ -1142,22 +1142,22 @@
std::string *code_ptr) {
std::string &code = *code_ptr;
- code += "func (rcv *" + namer_.Type(struct_def.name) + ") UnPackTo(t *" +
+ code += "func (rcv *" + namer_.Type(struct_def) + ") UnPackTo(t *" +
NativeName(struct_def) + ") {\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const FieldDef &field = **it;
if (field.value.type.base_type == BASE_TYPE_STRUCT) {
- code += "\tt." + namer_.Field(field.name) + " = rcv." +
- namer_.Method(field.name) + "(nil).UnPack()\n";
+ code += "\tt." + namer_.Field(field) + " = rcv." +
+ namer_.Method(field) + "(nil).UnPack()\n";
} else {
- code += "\tt." + namer_.Field(field.name) + " = rcv." +
- namer_.Method(field.name) + "()\n";
+ code += "\tt." + namer_.Field(field) + " = rcv." +
+ namer_.Method(field) + "()\n";
}
}
code += "}\n\n";
- code += "func (rcv *" + namer_.Type(struct_def.name) + ") UnPack() *" +
+ code += "func (rcv *" + namer_.Type(struct_def) + ") UnPack() *" +
NativeName(struct_def) + " {\n";
code += "\tif rcv == nil { return nil }\n";
code += "\tt := &" + NativeName(struct_def) + "{}\n";
@@ -1247,9 +1247,7 @@
std::string TypeName(const FieldDef &field) {
std::string prefix;
- if (field.IsScalarOptional()) {
- prefix = "*";
- }
+ if (field.IsScalarOptional()) { prefix = "*"; }
return prefix + GenTypeGet(field.value.type);
}
@@ -1274,9 +1272,7 @@
}
std::string GenConstant(const FieldDef &field) {
- if (field.IsScalarOptional()) {
- return "nil";
- }
+ if (field.IsScalarOptional()) { return "nil"; }
switch (field.value.type.base_type) {
case BASE_TYPE_BOOL:
return field.value.constant == "0" ? "false" : "true";
@@ -1285,11 +1281,11 @@
}
std::string NativeName(const StructDef &struct_def) const {
- return namer_.ObjectType(struct_def.name);
+ return namer_.ObjectType(struct_def);
}
std::string NativeName(const EnumDef &enum_def) const {
- return namer_.ObjectType(enum_def.name);
+ return namer_.ObjectType(enum_def);
}
std::string NativeType(const Type &type) {
@@ -1366,20 +1362,21 @@
while (code.length() > 2 && code.substr(code.length() - 2) == "\n\n") {
code.pop_back();
}
- std::string filename = namer_.Directories(ns.components) +
- namer_.File(def.name, SkipFile::Suffix);
+ std::string directory = namer_.Directories(ns);
+ std::string file = namer_.File(def, SkipFile::Suffix);
+ EnsureDirExists(directory);
+ std::string filename = directory + file;
return SaveFile(filename.c_str(), code, false);
}
// Create the full name of the imported namespace (format: A__B__C).
std::string NamespaceImportName(const Namespace *ns) const {
- return namer_.Namespace(ns->components);
+ return namer_.Namespace(*ns);
}
// Create the full path for the imported namespace (format: A/B/C).
std::string NamespaceImportPath(const Namespace *ns) const {
- return namer_.Directories(ns->components,
- SkipDir::OutputPathAndTrailingPathSeparator);
+ return namer_.Directories(*ns, SkipDir::OutputPathAndTrailingPathSeparator);
}
// Ensure that a type is prefixed with its go package import name if it is
diff --git a/third_party/flatbuffers/src/idl_gen_grpc.cpp b/third_party/flatbuffers/src/idl_gen_grpc.cpp
index 6894ffb..2be24e7 100644
--- a/third_party/flatbuffers/src/idl_gen_grpc.cpp
+++ b/third_party/flatbuffers/src/idl_gen_grpc.cpp
@@ -242,12 +242,6 @@
return StripExtension(file_name_);
}
- std::string message_header_ext() const {
- return parser_.opts.filename_suffix + ".h";
- }
-
- std::string service_header_ext() const { return ".grpc.fb.h"; }
-
std::string package() const {
return parser_.current_namespace_->GetFullyQualifiedName("");
}
@@ -347,6 +341,7 @@
bool GenerateCppGRPC(const Parser &parser, const std::string &path,
const std::string &file_name) {
+ const auto &opts = parser.opts;
int nservices = 0;
for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
++it) {
@@ -354,9 +349,15 @@
}
if (!nservices) return true;
+ std::string suffix = "";
+ suffix += opts.filename_suffix.empty() ? "_generated" : opts.filename_suffix;
+ suffix += ".";
+ suffix += opts.filename_extension.empty() ? "h" : opts.filename_extension;
+
grpc_cpp_generator::Parameters generator_parameters;
// TODO(wvo): make the other parameters in this struct configurable.
generator_parameters.use_system_headers = true;
+ generator_parameters.message_header_extension = suffix;
FlatBufFile fbfile(parser, file_name, FlatBufFile::kLanguageCpp);
diff --git a/third_party/flatbuffers/src/idl_gen_java.cpp b/third_party/flatbuffers/src/idl_gen_java.cpp
index ee09391..6ee97aa 100644
--- a/third_party/flatbuffers/src/idl_gen_java.cpp
+++ b/third_party/flatbuffers/src/idl_gen_java.cpp
@@ -20,20 +20,65 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
namespace java {
-static TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
+namespace {
+
+static Namer::Config JavaDefaultConfig() {
+ return {
+ /*types=*/Case::kKeep,
+ /*constants=*/Case::kScreamingSnake,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kLowerCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/".",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".java",
+ };
+}
+
+static std::set<std::string> JavaKeywords() {
+ return {
+ "abstract", "continue", "for", "new", "switch",
+ "assert", "default", "goto", "package", "synchronized",
+ "boolean", "do", "if", "private", "this",
+ "break", "double", "implements", "protected", "throw",
+ "byte", "else", "import", "public", "throws",
+ "case", "enum", "instanceof", "return", "transient",
+ "catch", "extends", "int", "short", "try",
+ "char", "final", "interface", "static", "void",
+ "class", "finally", "long", "strictfp", "volatile",
+ "const", "float", "native", "super", "while",
+ };
+}
+
+static const TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
"POSITIVE_INFINITY",
"NEGATIVE_INFINITY");
-static CommentConfig comment_config = {
+static const CommentConfig comment_config = {
"/**",
" *",
" */",
};
+} // namespace
+
class JavaGenerator : public BaseGenerator {
struct FieldArrayLength {
std::string name;
@@ -44,7 +89,9 @@
JavaGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", ".", "java"),
- cur_name_space_(nullptr) {}
+ cur_name_space_(nullptr),
+ namer_(WithFlagOptions(JavaDefaultConfig(), parser.opts, path),
+ JavaKeywords()) {}
JavaGenerator &operator=(const JavaGenerator &);
bool generate() {
@@ -56,7 +103,7 @@
std::string enumcode;
auto &enum_def = **it;
if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
- GenEnum(enum_def, &enumcode);
+ GenEnum(enum_def, enumcode);
if (parser_.opts.one_file) {
one_file_code += enumcode;
} else {
@@ -67,8 +114,8 @@
if (parser_.opts.generate_object_based_api && enum_def.is_union) {
enumcode = "";
- GenEnum_ObjectAPI(enum_def, &enumcode, parser_.opts);
- auto class_name = enum_def.name + "Union";
+ GenEnum_ObjectAPI(enum_def, enumcode);
+ auto class_name = namer_.Type(enum_def) + "Union";
if (parser_.opts.one_file) {
one_file_code += enumcode;
} else {
@@ -85,7 +132,7 @@
auto &struct_def = **it;
if (!parser_.opts.one_file)
cur_name_space_ = struct_def.defined_namespace;
- GenStruct(struct_def, &declcode, parser_.opts);
+ GenStruct(struct_def, declcode, parser_.opts);
if (parser_.opts.one_file) {
one_file_code += declcode;
} else {
@@ -96,8 +143,8 @@
if (parser_.opts.generate_object_based_api) {
declcode = "";
- GenStruct_ObjectAPI(struct_def, &declcode, parser_.opts);
- auto class_name = GenTypeName_ObjectAPI(struct_def.name, parser_.opts);
+ GenStruct_ObjectAPI(struct_def, declcode);
+ auto class_name = namer_.ObjectType(struct_def);
if (parser_.opts.one_file) {
one_file_code += declcode;
} else {
@@ -124,7 +171,7 @@
std::string code;
code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
- std::string namespace_name = FullNamespace(".", ns);
+ const std::string namespace_name = FullNamespace(".", ns);
if (!namespace_name.empty()) {
code += "package " + namespace_name + ";";
code += "\n\n";
@@ -144,7 +191,10 @@
code += classcode;
if (!namespace_name.empty()) code += "";
- auto filename = NamespaceDir(ns) + defname + ".java";
+ const std::string dirs = namer_.Directories(ns);
+ EnsureDirExists(dirs);
+ const std::string filename =
+ dirs + namer_.File(defname, /*skips=*/SkipFile::Suffix);
return SaveFile(filename.c_str(), code, false);
}
@@ -181,7 +231,7 @@
switch (type.base_type) {
case BASE_TYPE_STRING: return "String";
case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
- case BASE_TYPE_STRUCT: return WrapInNameSpace(*type.struct_def);
+ case BASE_TYPE_STRUCT: return namer_.NamespacedType(*type.struct_def);
case BASE_TYPE_UNION: FLATBUFFERS_FALLTHROUGH(); // else fall thru
default: return "Table";
}
@@ -285,7 +335,7 @@
FLATBUFFERS_ASSERT(value.type.enum_def);
auto &enum_def = *value.type.enum_def;
auto enum_val = enum_def.FindByValue(value.constant);
- return enum_val ? (WrapInNameSpace(enum_def) + "." + enum_val->name)
+ return enum_val ? namer_.NamespacedEnumVariant(enum_def, *enum_val)
: value.constant;
}
@@ -320,8 +370,7 @@
return GenDefaultValue(field);
}
- void GenEnum(EnumDef &enum_def, std::string *code_ptr) const {
- std::string &code = *code_ptr;
+ void GenEnum(EnumDef &enum_def, std::string &code) const {
if (enum_def.generated) return;
// Generate enum definitions of the form:
@@ -329,7 +378,7 @@
// In Java, we use ints rather than the Enum feature, because we want them
// to map directly to how they're used in C/C++ and file formats.
// That, and Java Enums are expensive, and not universally liked.
- GenComment(enum_def.doc_comment, code_ptr, &comment_config);
+ GenComment(enum_def.doc_comment, &code, &comment_config);
code += "@SuppressWarnings(\"unused\")\n";
if (enum_def.attributes.Lookup("private")) {
@@ -337,16 +386,16 @@
} else {
code += "public ";
}
- code += "final class " + enum_def.name;
+ code += "final class " + namer_.Type(enum_def);
code += " {\n";
- code += " private " + enum_def.name + "() { }\n";
+ code += " private " + namer_.Type(enum_def) + "() { }\n";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
- GenComment(ev.doc_comment, code_ptr, &comment_config, " ");
+ GenComment(ev.doc_comment, &code, &comment_config, " ");
code += " public static final ";
code += GenTypeBasic(DestinationType(enum_def.underlying_type, false));
code += " ";
- code += ev.name + " = ";
+ code += namer_.Variant(ev) + " = ";
code += enum_def.ToString(ev);
code += ";\n";
}
@@ -364,13 +413,14 @@
"long") {
code += "\n public static final String";
code += "[] names = { ";
- auto val = enum_def.Vals().front();
+ const EnumVal *prev = enum_def.Vals().front();
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
++it) {
- auto ev = *it;
- for (auto k = enum_def.Distance(val, ev); k > 1; --k) code += "\"\", ";
- val = ev;
- code += "\"" + (*it)->name + "\", ";
+ const EnumVal &ev = **it;
+ for (auto k = enum_def.Distance(prev, &ev); k > 1; --k)
+ code += "\"\", ";
+ prev = &ev;
+ code += "\"" + namer_.Variant(ev) + "\", ";
}
code += "};\n\n";
code += " public static ";
@@ -378,7 +428,7 @@
code += " name";
code += "(int e) { return names[e";
if (enum_def.MinValue()->IsNonZero())
- code += " - " + enum_def.MinValue()->name;
+ code += " - " + namer_.Variant(enum_def.MinValue()->name);
code += "]; }\n";
}
@@ -445,9 +495,8 @@
// Recursively generate arguments for a constructor, to deal with nested
// structs.
- void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
+ void GenStructArgs(const StructDef &struct_def, std::string &code,
const char *nameprefix, size_t array_count = 0) const {
- std::string &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
@@ -460,7 +509,7 @@
// 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.
- GenStructArgs(*field_type.struct_def, code_ptr,
+ GenStructArgs(*field_type.struct_def, code,
(nameprefix + (field.name + "_")).c_str(), array_cnt);
} else {
code += ", ";
@@ -468,7 +517,7 @@
for (size_t i = 0; i < array_cnt; i++) code += "[]";
code += " ";
code += nameprefix;
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += namer_.Field(field);
}
}
}
@@ -476,10 +525,9 @@
// Recusively generate struct construction statements of the form:
// builder.putType(name);
// and insert manual padding.
- void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
+ void GenStructBody(const StructDef &struct_def, std::string &code,
const char *nameprefix, size_t index = 0,
bool in_array = false) const {
- std::string &code = *code_ptr;
std::string indent((index + 1) * 2, ' ');
code += indent + " builder.prep(";
code += NumToString(struct_def.minalign) + ", ";
@@ -493,7 +541,7 @@
code += NumToString(field.padding) + ");\n";
}
if (IsStruct(field_type)) {
- GenStructBody(*field_type.struct_def, code_ptr,
+ GenStructBody(*field_type.struct_def, code,
(nameprefix + (field.name + "_")).c_str(), index,
in_array);
} else {
@@ -507,7 +555,7 @@
in_array = true;
}
if (IsStruct(type)) {
- GenStructBody(*field_type.struct_def, code_ptr,
+ GenStructBody(*field_type.struct_def, code,
(nameprefix + (field.name + "_")).c_str(), index + 1,
in_array);
} else {
@@ -515,8 +563,7 @@
code += indent + " builder.put";
code += GenMethod(type) + "(";
code += SourceCast(type);
- auto argname =
- nameprefix + ConvertCase(field.name, Case::kLowerCamel);
+ auto argname = nameprefix + namer_.Variable(field);
code += argname;
size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
for (size_t i = 0; in_array && i < array_cnt; i++) {
@@ -529,12 +576,6 @@
}
}
- std::string GenByteBufferLength(const char *bb_name) const {
- std::string bb_len = bb_name;
- bb_len += ".capacity()";
- return bb_len;
- }
-
std::string GenOffsetGetter(flatbuffers::FieldDef *key_field,
const char *num = nullptr) const {
std::string key_offset = "";
@@ -543,7 +584,7 @@
key_offset += num;
key_offset += ", _bb)";
} else {
- key_offset += GenByteBufferLength("bb");
+ key_offset += "bb.capacity()";
key_offset += " - tableOffset, bb)";
}
return key_offset;
@@ -592,10 +633,9 @@
return key_getter;
}
- void GenStruct(StructDef &struct_def, std::string *code_ptr,
+ void GenStruct(StructDef &struct_def, std::string &code,
const IDLOptions &opts) const {
if (struct_def.generated) return;
- std::string &code = *code_ptr;
// Generate a struct accessor class, with methods of the form:
// public type name() { return bb.getType(i + offset); }
@@ -603,7 +643,7 @@
// public type name() {
// int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default;
// }
- GenComment(struct_def.doc_comment, code_ptr, &comment_config);
+ GenComment(struct_def.doc_comment, &code, &comment_config);
if (parser_.opts.gen_generated) {
code += "@javax.annotation.Generated(value=\"flatc\")\n";
@@ -614,33 +654,35 @@
} else {
code += "public ";
}
- code += "final class " + struct_def.name;
+ const auto struct_class = namer_.Type(struct_def);
+ code += "final class " + struct_class;
code += " extends ";
code += struct_def.fixed ? "Struct" : "Table";
code += " {\n";
if (!struct_def.fixed) {
- // Generate verson check method.
+ // Generate version check method.
// Force compile time error if not using the same version runtime.
code += " public static void ValidateVersion() {";
code += " Constants.";
- code += "FLATBUFFERS_2_0_0(); ";
+ code += "FLATBUFFERS_2_0_8(); ";
code += "}\n";
// Generate a special accessor for the table that when used as the root
// of a FlatBuffer
- std::string method_name = "getRootAs" + struct_def.name;
- std::string method_signature =
- " public static " + struct_def.name + " " + method_name;
+ const std::string method_name =
+ namer_.LegacyJavaMethod2("getRootAs", struct_def, "");
+ const std::string method_signature =
+ " public static " + struct_class + " " + method_name;
// create convenience method that doesn't require an existing object
code += method_signature + "(ByteBuffer _bb) ";
- code += "{ return " + method_name + "(_bb, new " + struct_def.name +
- "()); }\n";
+ code +=
+ "{ return " + method_name + "(_bb, new " + struct_class + "()); }\n";
// create method that allows object reuse
code +=
- method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { ";
+ method_signature + "(ByteBuffer _bb, " + struct_class + " obj) { ";
code += "_bb.order(ByteOrder.LITTLE_ENDIAN); ";
code += "return (obj.__assign(_bb.getInt(_bb.";
code += "position()";
@@ -651,8 +693,10 @@
if (parser_.file_identifier_.length()) {
// Check if a buffer has the identifier.
code += " public static ";
- code += "boolean " + struct_def.name;
- code += "BufferHasIdentifier(ByteBuffer _bb) { return ";
+ code += "boolean " +
+ namer_.LegacyJavaMethod2(
+ "", struct_def, "BufferHasIdentifier(ByteBuffer _bb)") +
+ " { return ";
code += "__has_identifier(_bb, \"";
code += parser_.file_identifier_;
code += "\"); }\n";
@@ -665,27 +709,24 @@
code += "{ ";
code += "__reset(_i, _bb); ";
code += "}\n";
- code +=
- " public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) ";
+ code += " public " + struct_class + " __assign(int _i, ByteBuffer _bb) ";
code += "{ __init(_i, _bb); return this; }\n\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- GenComment(field.doc_comment, code_ptr, &comment_config, " ");
- std::string type_name = GenTypeGet(field.value.type);
- std::string type_name_dest = GenTypeNameDest(field.value.type);
- std::string conditional_cast = "";
- std::string optional = "";
- std::string dest_mask = DestinationMask(field.value.type, true);
- std::string dest_cast = DestinationCast(field.value.type);
- std::string src_cast = SourceCast(field.value.type);
- std::string method_start =
+ GenComment(field.doc_comment, &code, &comment_config, " ");
+ const std::string type_name = GenTypeGet(field.value.type);
+ const std::string type_name_dest = GenTypeNameDest(field.value.type);
+ const std::string dest_mask = DestinationMask(field.value.type, true);
+ const std::string dest_cast = DestinationCast(field.value.type);
+ const std::string src_cast = SourceCast(field.value.type);
+ const std::string method_start =
" public " +
(field.IsRequired() ? "" : GenNullableAnnotation(field.value.type)) +
- GenPureAnnotation(field.value.type) + type_name_dest + optional +
- " " + ConvertCase(field.name, Case::kLowerCamel);
- std::string obj = "obj";
+ GenPureAnnotation(field.value.type) + type_name_dest + " " +
+ namer_.Field(field);
+ const std::string obj = "obj";
// Most field accessors need to retrieve and test the field offset first,
// this is the prefix code for that:
@@ -698,7 +739,7 @@
if (field.value.type.base_type == BASE_TYPE_STRUCT) {
// Calls the accessor that takes an accessor object with a new object.
code += method_start + "() { return ";
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += namer_.Field(field);
code += "(new ";
code += type_name + "()); }\n";
} else if (IsSeries(field.value.type) &&
@@ -706,14 +747,13 @@
// Accessors for vectors of structs also take accessor objects, this
// generates a variant without that argument.
code += method_start + "(int j) { return ";
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += namer_.Field(field);
code += "(new " + type_name + "(), j); }\n";
}
if (field.IsScalarOptional()) { code += GenOptionalScalarCheck(field); }
std::string getter = dest_cast + GenGetter(field.value.type);
code += method_start;
- std::string default_cast = "";
std::string member_suffix = "; ";
if (IsScalar(field.value.type.base_type)) {
code += "()";
@@ -726,7 +766,7 @@
} else {
code += offset_prefix + getter;
code += "(o + bb_pos)" + dest_mask;
- code += " : " + default_cast;
+ code += " : ";
code += GenDefaultValue(field);
}
} else {
@@ -738,7 +778,7 @@
code += "bb_pos + " + NumToString(field.value.offset) + ", ";
code += "bb)";
} else {
- code += offset_prefix + conditional_cast;
+ code += offset_prefix;
code += obj + ".__assign(";
code += field.value.type.struct_def->fixed
? "o + bb_pos"
@@ -763,7 +803,7 @@
code += type_name + " obj, ";
}
code += "int j)";
- const auto body = offset_prefix + conditional_cast + getter + "(";
+ const auto body = offset_prefix + getter + "(";
if (vectortype.base_type == BASE_TYPE_UNION) {
code += body + "obj, ";
} else {
@@ -787,11 +827,9 @@
code += ")" + dest_mask;
if (!IsArray(field.value.type)) {
code += " : ";
- code +=
- field.value.type.element == BASE_TYPE_BOOL
- ? "false"
- : (IsScalar(field.value.type.element) ? default_cast + "0"
- : "null");
+ code += field.value.type.element == BASE_TYPE_BOOL
+ ? "false"
+ : (IsScalar(field.value.type.element) ? "0" : "null");
}
break;
@@ -806,7 +844,7 @@
code += member_suffix;
code += "}\n";
if (IsVector(field.value.type)) {
- code += " public int " + ConvertCase(field.name, Case::kLowerCamel);
+ code += " public int " + namer_.Field(field);
code += "Length";
code += "()";
code += offset_prefix;
@@ -821,9 +859,9 @@
for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
auto &key_field = **kit;
if (key_field.key) {
- auto qualified_name = WrapInNameSpace(sd);
+ auto qualified_name = namer_.NamespacedType(sd);
code += " public " + qualified_name + " ";
- code += ConvertCase(field.name, Case::kLowerCamel) + "ByKey(";
+ code += namer_.Method(field) + "ByKey(";
code += GenTypeNameDest(key_field.value.type) + " key)";
code += offset_prefix;
code += qualified_name + ".__lookup_by_key(";
@@ -832,7 +870,7 @@
code += "bb) : null; ";
code += "}\n";
code += " public " + qualified_name + " ";
- code += ConvertCase(field.name, Case::kLowerCamel) + "ByKey(";
+ code += namer_.Method(field) + "ByKey(";
code += qualified_name + " obj, ";
code += GenTypeNameDest(key_field.value.type) + " key)";
code += offset_prefix;
@@ -859,15 +897,14 @@
} else {
vector_type_name = type_name + ".Vector";
}
- auto vector_method_start =
- GenNullableAnnotation(field.value.type) + " public " +
- vector_type_name + optional + " " +
- ConvertCase(field.name, Case::kLowerCamel) + "Vector";
+ auto vector_method_start = GenNullableAnnotation(field.value.type) +
+ " public " + vector_type_name + " " +
+ namer_.Field(field, "vector");
code += vector_method_start + "() { return ";
- code += ConvertCase(field.name, Case::kLowerCamel) + "Vector";
+ code += namer_.Field(field, "vector");
code += "(new " + vector_type_name + "()); }\n";
code += vector_method_start + "(" + vector_type_name + " obj)";
- code += offset_prefix + conditional_cast + obj + ".__assign(";
+ code += offset_prefix + obj + ".__assign(";
code += "__vector(o), ";
if (!IsScalar(element_base_type)) {
auto vectortype = field.value.type.VectorType();
@@ -880,7 +917,7 @@
IsScalar(field.value.type.VectorType().base_type)) ||
IsString(field.value.type)) {
code += " public ByteBuffer ";
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += namer_.Field(field);
code += "AsByteBuffer() { return ";
code += "__vector_as_bytebuffer(";
code += NumToString(field.value.offset) + ", ";
@@ -889,7 +926,7 @@
: InlineSize(field.value.type.VectorType()));
code += "); }\n";
code += " public ByteBuffer ";
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += namer_.Field(field);
code += "InByteBuffer(ByteBuffer _bb) { return ";
code += "__vector_in_bytebuffer(_bb, ";
code += NumToString(field.value.offset) + ", ";
@@ -900,9 +937,9 @@
}
// generate object accessors if is nested_flatbuffer
if (field.nested_flatbuffer) {
- auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
- auto nested_method_name = ConvertCase(field.name, Case::kLowerCamel) +
- "As" + field.nested_flatbuffer->name;
+ auto nested_type_name = namer_.NamespacedType(*field.nested_flatbuffer);
+ auto nested_method_name =
+ namer_.Field(field) + "As" + field.nested_flatbuffer->name;
auto get_nested_method_name = nested_method_name;
code += " public " + nested_type_name + " ";
code += nested_method_name + "() { return ";
@@ -913,7 +950,7 @@
code += nested_type_name + " obj";
code += ") { int o = __offset(";
code += NumToString(field.value.offset) + "); ";
- code += "return o != 0 ? " + conditional_cast + obj + ".__assign(";
+ code += "return o != 0 ? " + obj + ".__assign(";
code += "";
code += "__indirect(__vector(o)), ";
code += "bb) : null; }\n";
@@ -928,7 +965,6 @@
auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
? "(byte)(" + field.name + " ? 1 : 0)"
: field.name;
- auto mutator_prefix = "mutate";
// A vector mutator also needs the index of the vector element it should
// mutate.
auto mutator_params = (is_series ? "(int j, " : "(") +
@@ -946,7 +982,7 @@
if (IsScalar(underlying_type.base_type) && !IsUnion(field.value.type)) {
code += " public ";
code += struct_def.fixed ? "void " : "boolean ";
- code += mutator_prefix + ConvertCase(field.name, Case::kUpperCamel);
+ code += namer_.Method("mutate", field);
code += mutator_params;
if (struct_def.fixed) {
code += GenSetter(underlying_type) + "(" + setter_index + ", ";
@@ -962,10 +998,9 @@
}
if (parser_.opts.java_primitive_has_method &&
IsScalar(field.value.type.base_type) && !struct_def.fixed) {
- auto vt_offset_constant =
- " public static final int VT_" +
- ConvertCase(field.name, Case::kScreamingSnake) + " = " +
- NumToString(field.value.offset) + ";";
+ auto vt_offset_constant = " public static final int VT_" +
+ namer_.Constant(field) + " = " +
+ NumToString(field.value.offset) + ";";
code += vt_offset_constant;
code += "\n";
@@ -980,10 +1015,10 @@
// create a struct constructor function
code += " public static " + GenOffsetType() + " ";
code += "create";
- code += struct_def.name + "(FlatBufferBuilder builder";
- GenStructArgs(struct_def, code_ptr, "");
+ code += struct_class + "(FlatBufferBuilder builder";
+ GenStructArgs(struct_def, code, "");
code += ") {\n";
- GenStructBody(struct_def, code_ptr, "");
+ GenStructBody(struct_def, code, "");
code += " return ";
code += GenOffsetConstruct("builder." + std::string("offset()"));
code += ";\n }\n";
@@ -1010,12 +1045,12 @@
// Generate a table constructor of the form:
// public static int createName(FlatBufferBuilder builder, args...)
code += " public static " + GenOffsetType() + " ";
- code += "create" + struct_def.name;
+ code += namer_.LegacyJavaMethod2("create", struct_def, "");
code += "(FlatBufferBuilder builder";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
- auto field_name = ConvertCase(field.name, Case::kLowerCamel);
+ auto field_name = namer_.Field(field);
if (field.deprecated) continue;
code += ",\n ";
code += GenTypeBasic(DestinationType(field.value.type, false));
@@ -1031,21 +1066,19 @@
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it;
- auto field_name = ConvertCase(field.name, Case::kLowerCamel);
- auto method_name = ConvertCase(field.name, Case::kUpperCamel);
+ auto field_name = namer_.Field(field);
if (!field.deprecated &&
(!struct_def.sortbysize ||
size == SizeOf(field.value.type.base_type))) {
- code += " " + struct_def.name + ".";
- code += "add";
- code += method_name + "(builder, " + field_name;
+ code += " " + struct_class + ".";
+ code += namer_.Method("add", field) + "(builder, " + field_name;
if (!IsScalar(field.value.type.base_type)) code += "Offset";
code += ");\n";
}
}
}
- code += " return " + struct_def.name + ".";
- code += "end" + struct_def.name;
+ code += " return " + struct_class + ".";
+ code += namer_.LegacyJavaMethod2("end", struct_def, "");
code += "(builder);\n }\n\n";
}
// Generate a set of static methods that allow table construction,
@@ -1054,7 +1087,7 @@
// { builder.addShort(id, name, default); }
// Unlike the Create function, these always work.
code += " public static void start";
- code += struct_def.name;
+ code += struct_class;
code += "(FlatBufferBuilder builder) { builder.";
code += "startTable(";
code += NumToString(struct_def.fields.vec.size()) + "); }\n";
@@ -1062,22 +1095,34 @@
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- if (field.key) key_field = &field;
- code += " public static void add";
- code += ConvertCase(field.name, Case::kUpperCamel);
+
+ code += " public static void " + namer_.Method("add", field);
code += "(FlatBufferBuilder builder, ";
code += GenTypeBasic(DestinationType(field.value.type, false));
- auto argname = ConvertCase(field.name, Case::kLowerCamel);
+ auto argname = namer_.Field(field);
if (!IsScalar(field.value.type.base_type)) argname += "Offset";
code += " " + argname + ") { builder.add";
code += GenMethod(field.value.type) + "(";
- code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
- code += SourceCastBasic(field.value.type);
- code += argname;
- code += ", ";
- code += SourceCastBasic(field.value.type);
- code += GenDefaultValue(field);
- code += "); }\n";
+
+ if (field.key) {
+ // field has key attribute, so always need to exist
+ // even if its value is equal to default.
+ // Generated code will bypass default checking
+ // resulting in { builder.addShort(name); slot(id); }
+ key_field = &field;
+ code += SourceCastBasic(field.value.type);
+ code += argname;
+ code += "); builder.slot(" +
+ NumToString(it - struct_def.fields.vec.begin()) + "); }\n";
+ } else {
+ code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
+ code += SourceCastBasic(field.value.type);
+ code += argname;
+ code += ", ";
+ code += SourceCastBasic(field.value.type);
+ code += GenDefaultValue(field);
+ code += "); }\n";
+ }
if (IsVector(field.value.type)) {
auto vector_type = field.value.type.VectorType();
auto alignment = InlineAlignment(vector_type);
@@ -1089,20 +1134,17 @@
vector_type.base_type == BASE_TYPE_UCHAR)) {
// Handle byte[] and ByteBuffers separately for Java
code += " public static " + GenVectorOffsetType() + " ";
- code += "create";
- code += ConvertCase(field.name, Case::kUpperCamel);
+ code += namer_.Method("create", field);
code += "Vector(FlatBufferBuilder builder, byte[] data) ";
code += "{ return builder.createByteVector(data); }\n";
code += " public static " + GenVectorOffsetType() + " ";
- code += "create";
- code += ConvertCase(field.name, Case::kUpperCamel);
+ code += namer_.Method("create", field);
code += "Vector(FlatBufferBuilder builder, ByteBuffer data) ";
code += "{ return builder.createByteVector(data); }\n";
} else {
code += " public static " + GenVectorOffsetType() + " ";
- code += "create";
- code += ConvertCase(field.name, Case::kUpperCamel);
+ code += namer_.Method("create", field);
code += "Vector(FlatBufferBuilder builder, ";
code += GenTypeBasic(DestinationType(vector_type, false)) +
"[] data) ";
@@ -1123,8 +1165,7 @@
}
// Generate a method to start a vector, data to be added manually
// after.
- code += " public static void start";
- code += ConvertCase(field.name, Case::kUpperCamel);
+ code += " public static void " + namer_.Method("start", field);
code += "Vector(FlatBufferBuilder builder, int numElems) ";
code += "{ builder.startVector(";
code += NumToString(elem_size);
@@ -1133,7 +1174,7 @@
}
}
code += " public static " + GenOffsetType() + " ";
- code += "end" + struct_def.name;
+ code += namer_.LegacyJavaMethod2("end", struct_def, "");
code += "(FlatBufferBuilder builder) {\n int o = builder.";
code += "endTable();\n";
for (auto it = struct_def.fields.vec.begin();
@@ -1150,8 +1191,9 @@
std::string size_prefix[] = { "", "SizePrefixed" };
for (int i = 0; i < 2; ++i) {
code += " public static void ";
- code += "finish" + size_prefix[i] + struct_def.name;
- code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType();
+ code += namer_.LegacyJavaMethod2("finish" + size_prefix[i],
+ struct_def, "Buffer");
+ code += "(FlatBufferBuilder builder, " + GenOffsetType();
code += " offset) {";
code += " builder.finish" + size_prefix[i] + "(offset";
@@ -1170,9 +1212,9 @@
code += GenKeyGetter(key_field);
code += " }\n";
- code += "\n public static " + struct_def.name;
+ code += "\n public static " + struct_class;
code += " __lookup_by_key(";
- code += struct_def.name + " obj, ";
+ code += struct_class + " obj, ";
code += "int vectorLocation, ";
code += GenTypeNameDest(key_field->value.type);
code += " key, ByteBuffer bb) {\n";
@@ -1194,15 +1236,15 @@
code += " span -= middle;\n";
code += " } else {\n";
code += " return ";
- code += "(obj == null ? new " + struct_def.name + "() : obj)";
+ code += "(obj == null ? new " + struct_class + "() : obj)";
code += ".__assign(tableOffset, bb);\n";
code += " }\n }\n";
code += " return null;\n";
code += " }\n";
}
- GenVectorAccessObject(struct_def, code_ptr);
+ GenVectorAccessObject(struct_def, code);
if (opts.generate_object_based_api) {
- GenPackUnPack_ObjectAPI(struct_def, code_ptr, opts, struct_has_create,
+ GenPackUnPack_ObjectAPI(struct_def, code, opts, struct_has_create,
field_has_create_set);
}
code += "}\n\n";
@@ -1210,14 +1252,12 @@
std::string GenOptionalScalarCheck(FieldDef &field) const {
if (!field.IsScalarOptional()) return "";
- return " public boolean has" + ConvertCase(field.name, Case::kUpperCamel) +
+ return " public boolean " + namer_.Method("has", field) +
"() { return 0 != __offset(" + NumToString(field.value.offset) +
"); }\n";
}
- void GenVectorAccessObject(StructDef &struct_def,
- std::string *code_ptr) const {
- auto &code = *code_ptr;
+ void GenVectorAccessObject(StructDef &struct_def, std::string &code) const {
// Generate a vector of structs accessor class.
code += "\n";
code += " ";
@@ -1234,7 +1274,7 @@
code += "__assign(int _vector, int _element_size, ByteBuffer _bb) { ";
code += "__reset(_vector, _element_size, _bb); return this; }\n\n";
- auto type_name = struct_def.name;
+ auto type_name = namer_.Type(struct_def);
auto method_start = method_indent + "public " + type_name + " get";
// Generate the accessors that don't do object reuse.
code += method_start + "(int j) { return get";
@@ -1276,18 +1316,12 @@
code += " }\n";
}
- std::string GenGetterFuncName_ObjectAPI(const std::string &field_name) const {
- return "get" + ConvertCase(field_name, Case::kUpperCamel);
- }
-
- void GenEnum_ObjectAPI(EnumDef &enum_def, std::string *code_ptr,
- const IDLOptions &opts) const {
- auto &code = *code_ptr;
+ void GenEnum_ObjectAPI(EnumDef &enum_def, std::string &code) const {
if (enum_def.generated) return;
code += "import com.google.flatbuffers.FlatBufferBuilder;\n\n";
if (!enum_def.attributes.Lookup("private")) { code += "public "; }
- auto union_name = enum_def.name + "Union";
+ auto union_name = namer_.Type(enum_def) + "Union";
auto union_type =
GenTypeBasic(DestinationType(enum_def.underlying_type, false));
code += "class " + union_name + " {\n";
@@ -1304,15 +1338,16 @@
code += " public void setValue(Object value) { this.value = value; }\n\n";
// Constructor
code += " public " + union_name + "() {\n";
- code += " this.type = " + enum_def.name + "." +
- enum_def.Vals()[0]->name + ";\n";
+ code +=
+ " this.type = " + namer_.EnumVariant(enum_def, *enum_def.Vals()[0]) +
+ ";\n";
code += " this.value = null;\n";
code += " }\n\n";
// As
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
if (ev.union_type.base_type == BASE_TYPE_NONE) continue;
- auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts, false, true);
+ auto type_name = GenTypeGet_ObjectAPI(ev.union_type, false, true);
if (ev.union_type.base_type == BASE_TYPE_STRUCT &&
ev.union_type.struct_def->attributes.Lookup("private")) {
code += " ";
@@ -1332,7 +1367,7 @@
if (ev.union_type.base_type == BASE_TYPE_NONE) {
continue;
} else {
- code += " case " + enum_def.name + "." + ev.name + ": return ";
+ code += " case " + namer_.EnumVariant(enum_def, ev) + ": return ";
if (IsString(ev.union_type)) {
code += "builder.createString(_o.as" + ev.name + "());\n";
} else {
@@ -1347,41 +1382,23 @@
code += "}\n\n";
}
- std::string GenSetterFuncName_ObjectAPI(const std::string &field_name) const {
- return "set" + ConvertCase(field_name, Case::kUpperCamel);
- }
-
- std::string GenTypeName_ObjectAPI(const std::string &name,
- const IDLOptions &opts) const {
- return opts.object_prefix + name + opts.object_suffix;
- }
-
- void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string *code_ptr,
+ void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string &code,
const std::string &type_name,
- const std::string &camel_name,
+ const std::string &field_name,
bool is_vector) const {
- auto &code = *code_ptr;
+ const std::string variable_type =
+ is_vector ? type_name.substr(0, type_name.length() - 2) : type_name;
+ const std::string variable_name =
+ "_" + namer_.Variable("o", field_name) + (is_vector ? "Element" : "");
+ const std::string type_params = is_vector ? "_j" : "";
+ const std::string value_params = is_vector ? ", _j" : "";
+ const std::string indent = (is_vector ? " " : " ");
- std::string variable_type = type_name;
- std::string variable_name =
- "_o" + ConvertCase(camel_name, Case::kUpperCamel);
- std::string type_params = "";
- std::string value_params = "";
- std::string func_suffix = "()";
- std::string indent = " ";
- if (is_vector) {
- variable_type = type_name.substr(0, type_name.length() - 2);
- variable_name += "Element";
- type_params = "_j";
- value_params = ", _j";
- func_suffix = "(_j)";
- indent = " ";
- }
code += indent + variable_type + " " + variable_name + " = new " +
variable_type + "();\n";
code += indent +
GenTypeBasic(DestinationType(enum_def.underlying_type, false)) +
- " " + variable_name + "Type = " + camel_name + "Type(" +
+ " " + variable_name + "Type = " + field_name + "Type(" +
type_params + ");\n";
code += indent + variable_name + ".setType(" + variable_name + "Type);\n";
code += indent + "Table " + variable_name + "Value;\n";
@@ -1399,10 +1416,10 @@
// Java which doesn't handle non Table types. Should be
// deleted when issue #6561 is fixed.
}
- code += indent + " case " + WrapInNameSpace(enum_def) + "." + ev.name +
- ":\n";
+ code += indent + " case " +
+ namer_.NamespacedEnumVariant(enum_def, ev) + ":\n";
auto actual_type = GenTypeGet(ev.union_type);
- code += indent + " " + variable_name + "Value = " + camel_name +
+ code += indent + " " + variable_name + "Value = " + field_name +
"(new " + actual_type + "()" + value_params + ");\n";
code += indent + " " + variable_name + ".setValue(" + variable_name +
"Value != null ? ((" + actual_type + ") " + variable_name +
@@ -1413,17 +1430,16 @@
code += indent + " default: break;\n";
code += indent + "}\n";
if (is_vector) {
- code += indent + "_o" + ConvertCase(camel_name, Case::kUpperCamel) +
+ code += indent + "_" + namer_.Variable("o", field_name) +
"[_j] = " + variable_name + ";\n";
}
}
void GenPackUnPack_ObjectAPI(
- StructDef &struct_def, std::string *code_ptr, const IDLOptions &opts,
+ StructDef &struct_def, std::string &code, const IDLOptions &opts,
bool struct_has_create,
const std::set<FieldDef *> &field_has_create) const {
- auto &code = *code_ptr;
- auto struct_name = GenTypeName_ObjectAPI(struct_def.name, opts);
+ auto struct_name = namer_.ObjectType(struct_def);
// unpack()
code += " public " + struct_name + " unpack() {\n";
code += " " + struct_name + " _o = new " + struct_name + "();\n";
@@ -1434,35 +1450,34 @@
code += " public void unpackTo(" + struct_name + " _o) {\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
if (field.value.type.element == BASE_TYPE_UTYPE) continue;
- auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
- auto camel_name_with_first = ConvertCase(field.name, Case::kUpperCamel);
- auto type_name =
- GenTypeGet_ObjectAPI(field.value.type, opts, false, true);
+ const auto accessor = namer_.Method(field);
+ const auto variable = "_" + namer_.Variable("o", field);
+ const auto get_field = namer_.Method("get", field);
+ const auto set_field = namer_.Method("set", field);
+
+ auto type_name = GenTypeGet_ObjectAPI(field.value.type, false, true);
if (field.IsScalarOptional())
type_name = ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(type_name);
- auto start = " " + type_name + " _o" + camel_name_with_first + " = ";
+ auto start = " " + type_name + " " + variable + " = ";
auto call_setter = true;
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
auto fixed = struct_def.fixed && field.value.type.struct_def->fixed;
if (fixed) {
- code += " " + camel_name + "().unpackTo(_o.get" +
- camel_name_with_first + "());\n";
+ code +=
+ " " + accessor + "().unpackTo(_o." + get_field + "());\n";
} else {
- code += " if (" + camel_name + "() != null) ";
+ code += " if (" + accessor + "() != null) ";
if (field.value.type.struct_def->fixed) {
- code += camel_name + "().unpackTo(_o.get" +
- camel_name_with_first + "());\n";
+ code += accessor + "().unpackTo(_o." + get_field + "());\n";
} else {
- code += "_o." + GenSetterFuncName_ObjectAPI(field.name) + "(" +
- camel_name + "().unpack());\n";
+ code += "_o." + set_field + "(" + accessor + "().unpack());\n";
}
- code += " else _o." + GenSetterFuncName_ObjectAPI(field.name) +
- "(null);\n";
+ code += " else _o." + set_field + "(null);\n";
}
call_setter = false;
break;
@@ -1471,38 +1486,38 @@
auto length_str = NumToString(field.value.type.fixed_length);
auto unpack_method =
field.value.type.struct_def == nullptr ? "" : ".unpack()";
- code +=
- start + "_o." + GenGetterFuncName_ObjectAPI(field.name) + "();\n";
- code += " for (int _j = 0; _j < " + length_str + "; ++_j) { _o" +
- camel_name_with_first + "[_j] = " + camel_name + "(_j)" +
- unpack_method + "; }\n";
+ code += start + "_o." + get_field + "();\n";
+ code += " for (int _j = 0; _j < " + length_str + "; ++_j) { " +
+ variable + "[_j] = " + accessor + "(_j)" + unpack_method +
+ "; }\n";
call_setter = false;
break;
}
case BASE_TYPE_VECTOR:
if (field.value.type.element == BASE_TYPE_UNION) {
code += start + "new " +
- GenConcreteTypeGet_ObjectAPI(field.value.type, opts)
+ GenConcreteTypeGet_ObjectAPI(field.value.type)
.substr(0, type_name.length() - 1) +
- camel_name + "Length()];\n";
- code += " for (int _j = 0; _j < " + camel_name +
- "Length(); ++_j) {\n";
- GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
- type_name, camel_name, true);
+ accessor + "Length()];\n";
+ code +=
+ " for (int _j = 0; _j < " + accessor + "Length(); ++_j) {\n";
+ GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code,
+ type_name, accessor, true);
code += " }\n";
} else if (field.value.type.element != BASE_TYPE_UTYPE) {
auto fixed = field.value.type.struct_def == nullptr;
+ const auto length_accessor = namer_.Method(field, "length");
code += start + "new " +
- GenConcreteTypeGet_ObjectAPI(field.value.type, opts)
+ GenConcreteTypeGet_ObjectAPI(field.value.type)
.substr(0, type_name.length() - 1) +
- camel_name + "Length()];\n";
+ length_accessor + "()];\n";
code +=
- " for (int _j = 0; _j < " + camel_name + "Length(); ++_j) {";
- code += "_o" + camel_name_with_first + "[_j] = ";
+ " for (int _j = 0; _j < " + length_accessor + "(); ++_j) {";
+ code += variable + "[_j] = ";
if (fixed) {
- code += camel_name + "(_j)";
+ code += accessor + "(_j)";
} else {
- code += "(" + camel_name + "(_j) != null ? " + camel_name +
+ code += "(" + accessor + "(_j) != null ? " + accessor +
"(_j).unpack() : null)";
}
code += ";}\n";
@@ -1510,23 +1525,22 @@
break;
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_UNION: {
- GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
- type_name, camel_name, false);
+ GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code, type_name,
+ accessor, false);
break;
}
default: {
if (field.IsScalarOptional()) {
- code += start + "has" + camel_name_with_first + "() ? " +
- camel_name + "() : null;\n";
+ code += start + namer_.Method("has", field) + "() ? " + accessor +
+ "() : null;\n";
} else {
- code += start + camel_name + "();\n";
+ code += start + accessor + "();\n";
}
break;
}
}
if (call_setter) {
- code += " _o." + GenSetterFuncName_ObjectAPI(field.name) + "(_o" +
- camel_name_with_first + ");\n";
+ code += " _o." + set_field + "(" + variable + ");\n";
}
}
code += " }\n";
@@ -1538,17 +1552,17 @@
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
- auto camel_name_with_first = ConvertCase(field.name, Case::kUpperCamel);
+ const auto field_name = namer_.Field(field);
+ const auto variable = "_" + namer_.Variable("o", field);
+ const auto get_field = namer_.Method("get", field);
// pre
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (!field.value.type.struct_def->fixed) {
- code += " " + GenOffsetType() + " _" + field.name + " = _o." +
- GenGetterFuncName_ObjectAPI(field.name) +
+ code += " " + GenOffsetType() + " _" + namer_.Variable(field) +
+ " = _o." + get_field +
"() == null ? 0 : " + GenTypeGet(field.value.type) +
- ".pack(builder, _o." +
- GenGetterFuncName_ObjectAPI(field.name) + "());\n";
+ ".pack(builder, _o." + get_field + "());\n";
} else if (struct_def.fixed && struct_has_create) {
std::vector<FieldArrayLength> array_lengths;
FieldArrayLength tmp_array_length = {
@@ -1556,60 +1570,54 @@
field.value.type.fixed_length,
};
array_lengths.push_back(tmp_array_length);
- GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
- array_lengths);
+ GenStructPackDecl_ObjectAPI(*field.value.type.struct_def,
+ array_lengths, code);
}
break;
}
case BASE_TYPE_STRING: {
- std::string create_string = "createString";
- code += " int _" + camel_name + " = _o." +
- GenGetterFuncName_ObjectAPI(field.name) +
+ code += " int _" + field_name + " = _o." + get_field +
"() == null ? 0 : "
- "builder." +
- create_string + "(_o." +
- GenGetterFuncName_ObjectAPI(field.name) + "());\n";
+ "builder.createString(_o." +
+ get_field + "());\n";
break;
}
case BASE_TYPE_VECTOR: {
if (field_has_create.find(&field) != field_has_create.end()) {
- auto property_name = camel_name;
+ auto property_name = field_name;
auto gen_for_loop = true;
- std::string array_name = "__" + camel_name;
+ std::string array_name = "__" + field_name;
std::string array_type = "";
std::string element_type = "";
std::string to_array = "";
switch (field.value.type.element) {
case BASE_TYPE_STRING: {
- std::string create_string = "createString";
array_type = "int";
element_type = "String";
- to_array += "builder." + create_string + "(_e)";
+ to_array = "builder.createString(_e)";
break;
}
case BASE_TYPE_STRUCT:
array_type = "int";
element_type =
- GenTypeGet_ObjectAPI(field.value.type, opts, true, true);
+ GenTypeGet_ObjectAPI(field.value.type, true, true);
;
to_array = GenTypeGet(field.value.type) + ".pack(builder, _e)";
break;
case BASE_TYPE_UTYPE:
- property_name = camel_name.substr(0, camel_name.size() - 4);
+ property_name = field_name.substr(0, field_name.size() - 4);
array_type = GenTypeBasic(DestinationType(
field.value.type.enum_def->underlying_type, false));
element_type = field.value.type.enum_def->name + "Union";
- to_array = "_o." + GenGetterFuncName_ObjectAPI(property_name) +
+ to_array = "_o." + namer_.Method("get", property_name) +
"()[_j].getType()";
break;
case BASE_TYPE_UNION:
array_type = "int";
element_type =
- WrapInNameSpace(*field.value.type.enum_def) + "Union";
- to_array = WrapInNameSpace(*field.value.type.enum_def) +
- "Union.pack(builder, _o." +
- GenGetterFuncName_ObjectAPI(property_name) +
- "()[_j])";
+ namer_.NamespacedType(*field.value.type.enum_def) + "Union";
+ to_array = element_type + ".pack(builder, _o." +
+ namer_.Method("get", property_name) + "()[_j])";
break;
case BASE_TYPE_UCHAR: // TODO this branch of the switch is due to
// inconsistent behavior in unsigned byte.
@@ -1620,52 +1628,51 @@
break;
default:
gen_for_loop = false;
- array_name =
- "_o." + GenGetterFuncName_ObjectAPI(property_name) + "()";
+ array_name = "_o." + namer_.Method("get", property_name) + "()";
array_type = GenTypeNameDest(field.value.type);
element_type = array_type;
to_array = "_e";
break;
}
- code += " int _" + camel_name + " = 0;\n";
- code += " if (_o." + GenGetterFuncName_ObjectAPI(property_name) +
+ code += " int _" + field_name + " = 0;\n";
+ code += " if (_o." + namer_.Method("get", property_name) +
"() != null) {\n";
if (gen_for_loop) {
code += " " + array_type + "[] " + array_name + " = new " +
array_type + "[_o." +
- GenGetterFuncName_ObjectAPI(property_name) +
- "().length];\n";
+ namer_.Method("get", property_name) + "().length];\n";
code += " int _j = 0;\n";
code += " for (" + element_type + " _e : _o." +
- GenGetterFuncName_ObjectAPI(property_name) + "()) { ";
+ namer_.Method("get", property_name) + "()) { ";
code += array_name + "[_j] = " + to_array + "; _j++;}\n";
}
- code += " _" + camel_name + " = create" +
- camel_name_with_first + "Vector(builder, " + array_name +
- ");\n";
+ code += " _" + field_name + " = " +
+ namer_.Method("create", field) + "Vector(builder, " +
+ array_name + ");\n";
code += " }\n";
} else {
auto type_name = GenTypeGet(field.value.type);
auto element_type_name =
- GenTypeGet_ObjectAPI(field.value.type, opts, true, true);
+ GenTypeGet_ObjectAPI(field.value.type, true, true);
auto pack_method =
field.value.type.struct_def == nullptr
? "builder.add" + GenMethod(field.value.type.VectorType()) +
- "(_o" + camel_name_with_first + "[_j]);"
- : type_name + ".pack(builder, _o" + camel_name_with_first +
- "[_j]);";
- code += " int _" + camel_name + " = 0;\n";
- code += " " + element_type_name + "[] _o" +
- camel_name_with_first + " = _o." +
- GenGetterFuncName_ObjectAPI(field.name) + "();\n";
- code += " if (_o" + camel_name_with_first + " != null) {\n";
- code += " start" + camel_name_with_first +
- "Vector(builder, _o" + camel_name_with_first +
- ".length);\n";
- code += " for (int _j = _o" + camel_name_with_first +
+ "(" + variable + "[_j]);"
+ : "_unused_offset = " + type_name + ".pack(builder, " +
+ variable + "[_j]);";
+ code += " int _" + field_name + " = 0;\n";
+ code += " " + element_type_name + "[] " + variable + " = _o." +
+ get_field + "();\n";
+ code += " if (" + variable + " != null) {\n";
+ if (field.value.type.struct_def != nullptr) {
+ code += " int _unused_offset = 0;\n";
+ }
+ code += " " + namer_.Method("start", field) +
+ "Vector(builder, " + variable + ".length);\n";
+ code += " for (int _j = " + variable +
".length - 1; _j >=0; _j--) { ";
code += pack_method + "}\n";
- code += " _" + camel_name + " = builder.endVector();\n";
+ code += " _" + field_name + " = builder.endVector();\n";
code += " }\n";
}
break;
@@ -1678,29 +1685,27 @@
field.value.type.fixed_length,
};
array_lengths.push_back(tmp_array_length);
- GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
- array_lengths);
+ GenStructPackDecl_ObjectAPI(*field.value.type.struct_def,
+ array_lengths, code);
} else {
code += " " +
- GenTypeGet_ObjectAPI(field.value.type, opts, false, true) +
- " _" + camel_name + " = _o." +
- GenGetterFuncName_ObjectAPI(field.name) + "();\n";
+ GenTypeGet_ObjectAPI(field.value.type, false, true) + " _" +
+ field_name + " = _o." + get_field + "();\n";
}
break;
}
case BASE_TYPE_UNION: {
- code +=
- " " +
- GenTypeBasic(DestinationType(
- field.value.type.enum_def->underlying_type, false)) +
- " _" + camel_name + "Type = _o.get" + camel_name_with_first +
- "() == null ? " + WrapInNameSpace(*field.value.type.enum_def) +
- ".NONE : " + "_o.get" + camel_name_with_first + "().getType();\n";
- code += " " + GenOffsetType() + " _" + camel_name + " = _o.get" +
- camel_name_with_first + "() == null ? 0 : " +
- WrapInNameSpace(*field.value.type.enum_def) +
- "Union.pack(builder, _o.get" + camel_name_with_first +
- "());\n";
+ code += " " +
+ GenTypeBasic(DestinationType(
+ field.value.type.enum_def->underlying_type, false)) +
+ " _" + field_name + "Type = _o." + get_field +
+ "() == null ? " +
+ namer_.NamespacedType(*field.value.type.enum_def) +
+ ".NONE : " + "_o." + get_field + "().getType();\n";
+ code += " " + GenOffsetType() + " _" + field_name + " = _o." +
+ get_field + "() == null ? 0 : " +
+ namer_.NamespacedType(*field.value.type.enum_def) +
+ "Union.pack(builder, _o." + get_field + "());\n";
break;
}
default: break;
@@ -1708,42 +1713,42 @@
}
if (struct_has_create) {
// Create
- code += " return create" + struct_def.name + "(\n";
+ code += " return " +
+ namer_.LegacyJavaMethod2("create", struct_def, "") + "(\n";
code += " builder";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
+ const auto field_name = namer_.Field(field);
+ const auto get_field = namer_.Method("get", field);
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (struct_def.fixed) {
- GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
- code_ptr,
- " _" + camel_name + "_");
+ GenStructPackCall_ObjectAPI(*field.value.type.struct_def, code,
+ " _" + field_name + "_");
} else {
code += ",\n";
if (field.value.type.struct_def->fixed) {
if (opts.generate_object_based_api)
- code += " _o." + camel_name;
+ code += " _o." + field_name;
else
// Seems like unreachable code
code += " " + GenTypeGet(field.value.type) +
- ".Pack(builder, _o." + camel_name + ")";
+ ".Pack(builder, _o." + field_name + ")";
} else {
- code += " _" + field.name;
+ code += " _" + field_name;
}
}
break;
}
case BASE_TYPE_ARRAY: {
if (field.value.type.struct_def != nullptr) {
- GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
- code_ptr,
- " _" + camel_name + "_");
+ GenStructPackCall_ObjectAPI(*field.value.type.struct_def, code,
+ " _" + field_name + "_");
} else {
code += ",\n";
- code += " _" + camel_name;
+ code += " _" + field_name;
}
break;
}
@@ -1752,82 +1757,78 @@
case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_VECTOR: {
code += ",\n";
- code += " _" + camel_name;
+ code += " _" + field_name;
break;
}
default: // scalar
code += ",\n";
- code +=
- " _o." + GenGetterFuncName_ObjectAPI(field.name) + "()";
+ code += " _o." + get_field + "()";
break;
}
}
code += ");\n";
} else {
// Start, End
- code += " start" + struct_def.name + "(builder);\n";
+ code += " " + namer_.LegacyJavaMethod2("start", struct_def, "") +
+ "(builder);\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
- auto camel_name_with_first = ConvertCase(field.name, Case::kUpperCamel);
+ const auto arg = "_" + namer_.Variable(field);
+ const auto get_field = namer_.Method("get", field);
+ const auto add_field = namer_.Method("add", field);
+
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (field.value.type.struct_def->fixed) {
- code += " add" + camel_name_with_first + "(builder, " +
+ code += " " + add_field + "(builder, " +
GenTypeGet(field.value.type) + ".pack(builder, _o." +
- GenGetterFuncName_ObjectAPI(field.name) + "()));\n";
+ get_field + "()));\n";
} else {
- code += " add" + camel_name_with_first + "(builder, _" +
- field.name + ");\n";
+ code += " " + add_field + "(builder, " + arg + ");\n";
}
break;
}
case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_VECTOR: {
- code += " add" + camel_name_with_first + "(builder, _" +
- camel_name + ");\n";
+ code += " " + add_field + "(builder, " + arg + ");\n";
break;
}
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_UNION: {
- code += " add" + camel_name_with_first + "Type(builder, _" +
- camel_name + "Type);\n";
- code += " add" + camel_name_with_first + "(builder, _" +
- camel_name + ");\n";
+ code += " " + add_field + "Type(builder, " + arg + "Type);\n";
+ code += " " + add_field + "(builder, " + arg + ");\n";
break;
}
// scalar
default: {
if (field.IsScalarOptional()) {
- code += " if (_o." + GenGetterFuncName_ObjectAPI(field.name) +
- "() != null) { add" + camel_name_with_first +
- "(builder, _o." +
- GenGetterFuncName_ObjectAPI(field.name) + "()); }\n";
+ code += " if (_o." + get_field + "() != null) { " + add_field +
+ "(builder, _o." + get_field + "()); }\n";
} else {
- code += " add" + camel_name_with_first + "(builder, _o." +
- GenGetterFuncName_ObjectAPI(field.name) + "());\n";
+ code +=
+ " " + add_field + "(builder, _o." + get_field + "());\n";
}
break;
}
}
}
- code += " return end" + struct_def.name + "(builder);\n";
+ code += " return " + namer_.LegacyJavaMethod2("end", struct_def, "") +
+ "(builder);\n";
}
code += " }\n";
}
- void GenStructPackDecl_ObjectAPI(
- const StructDef &struct_def, std::string *code_ptr,
- std::vector<FieldArrayLength> &array_lengths) const {
- auto &code = *code_ptr;
+ void GenStructPackDecl_ObjectAPI(const StructDef &struct_def,
+ std::vector<FieldArrayLength> &array_lengths,
+ std::string &code) const {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
- auto is_array = IsArray(field.value.type);
- const auto &field_type =
+ const FieldDef &field = **it;
+ const bool is_array = IsArray(field.value.type);
+ const Type &field_type =
is_array ? field.value.type.VectorType() : field.value.type;
FieldArrayLength tmp_array_length = {
field.name,
@@ -1835,8 +1836,8 @@
};
array_lengths.push_back(tmp_array_length);
if (field_type.struct_def != nullptr) {
- GenStructPackDecl_ObjectAPI(*field_type.struct_def, code_ptr,
- array_lengths);
+ GenStructPackDecl_ObjectAPI(*field_type.struct_def, array_lengths,
+ code);
} else {
std::vector<FieldArrayLength> array_only_lengths;
for (size_t i = 0; i < array_lengths.size(); ++i) {
@@ -1846,7 +1847,7 @@
}
std::string name;
for (size_t i = 0; i < array_lengths.size(); ++i) {
- name += "_" + ConvertCase(array_lengths[i].name, Case::kLowerCamel);
+ name += "_" + namer_.Variable(array_lengths[i].name);
}
code += " " + GenTypeBasic(field_type);
if (array_only_lengths.size() > 0) {
@@ -1878,8 +1879,7 @@
}
code += "] = _o";
for (size_t i = 0, j = 0; i < array_lengths.size(); ++i) {
- code +=
- "." + GenGetterFuncName_ObjectAPI(array_lengths[i].name) + "()";
+ code += "." + namer_.Method("get", array_lengths[i].name) + "()";
if (array_lengths[i].length <= 0) continue;
code += "[idx" + NumToString(j++) + "]";
}
@@ -1891,8 +1891,7 @@
code += " " + name + " = ";
code += "_o";
for (size_t i = 0; i < array_lengths.size(); ++i) {
- code +=
- "." + GenGetterFuncName_ObjectAPI(array_lengths[i].name) + "()";
+ code += "." + namer_.Method("get", array_lengths[i].name) + "()";
}
code += ";";
}
@@ -1903,26 +1902,24 @@
}
void GenStructPackCall_ObjectAPI(const StructDef &struct_def,
- std::string *code_ptr,
+ std::string &code,
std::string prefix) const {
- auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
const auto &field_type = field.value.type;
if (field_type.struct_def != nullptr) {
- GenStructPackCall_ObjectAPI(
- *field_type.struct_def, code_ptr,
- prefix + ConvertCase(field.name, Case::kLowerCamel) + "_");
+ GenStructPackCall_ObjectAPI(*field_type.struct_def, code,
+ prefix + namer_.Field(field) + "_");
} else {
code += ",\n";
- code += prefix + ConvertCase(field.name, Case::kLowerCamel);
+ code += prefix + namer_.Field(field);
}
}
}
std::string ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(
- std::string type_name) const {
+ const std::string &type_name) const {
if (type_name == "boolean")
return "Boolean";
else if (type_name == "byte")
@@ -1942,8 +1939,8 @@
return type_name;
}
- std::string GenTypeGet_ObjectAPI(flatbuffers::Type type,
- const IDLOptions &opts, bool vectorelem,
+ std::string GenTypeGet_ObjectAPI(const flatbuffers::Type &type,
+ bool vectorelem,
bool wrap_in_namespace) const {
auto type_name = GenTypeNameDest(type);
// Replace to ObjectBaseAPI Type Name
@@ -1953,15 +1950,14 @@
case BASE_TYPE_VECTOR: {
if (type.struct_def != nullptr) {
auto type_name_length = type.struct_def->name.length();
- auto new_type_name =
- GenTypeName_ObjectAPI(type.struct_def->name, opts);
+ auto new_type_name = namer_.ObjectType(*type.struct_def);
type_name.replace(type_name.length() - type_name_length,
type_name_length, new_type_name);
} else if (type.element == BASE_TYPE_UNION) {
if (wrap_in_namespace) {
- type_name = WrapInNameSpace(*type.enum_def) + "Union";
+ type_name = namer_.NamespacedType(*type.enum_def) + "Union";
} else {
- type_name = type.enum_def->name + "Union";
+ type_name = namer_.Type(*type.enum_def) + "Union";
}
}
break;
@@ -1969,9 +1965,9 @@
case BASE_TYPE_UNION: {
if (wrap_in_namespace) {
- type_name = WrapInNameSpace(*type.enum_def) + "Union";
+ type_name = namer_.NamespacedType(*type.enum_def) + "Union";
} else {
- type_name = type.enum_def->name + "Union";
+ type_name = namer_.Type(*type.enum_def) + "Union";
}
break;
}
@@ -1989,8 +1985,8 @@
return type_name;
}
- std::string GenConcreteTypeGet_ObjectAPI(flatbuffers::Type type,
- const IDLOptions &opts) const {
+ std::string GenConcreteTypeGet_ObjectAPI(
+ const flatbuffers::Type &type) const {
auto type_name = GenTypeNameDest(type);
// Replace to ObjectBaseAPI Type Name
switch (type.base_type) {
@@ -1999,18 +1995,17 @@
case BASE_TYPE_VECTOR: {
if (type.struct_def != nullptr) {
auto type_name_length = type.struct_def->name.length();
- auto new_type_name =
- GenTypeName_ObjectAPI(type.struct_def->name, opts);
+ auto new_type_name = namer_.ObjectType(*type.struct_def);
type_name.replace(type_name.length() - type_name_length,
type_name_length, new_type_name);
} else if (type.element == BASE_TYPE_UNION) {
- type_name = WrapInNameSpace(*type.enum_def) + "Union";
+ type_name = namer_.NamespacedType(*type.enum_def) + "Union";
}
break;
}
case BASE_TYPE_UNION: {
- type_name = WrapInNameSpace(*type.enum_def) + "Union";
+ type_name = namer_.NamespacedType(*type.enum_def) + "Union";
break;
}
default: break;
@@ -2027,71 +2022,71 @@
return type_name;
}
- void GenStruct_ObjectAPI(StructDef &struct_def, std::string *code_ptr,
- const IDLOptions &opts) const {
+ void GenStruct_ObjectAPI(const StructDef &struct_def,
+ std::string &code) const {
if (struct_def.generated) return;
- auto &code = *code_ptr;
if (struct_def.attributes.Lookup("private")) {
// For Java, we leave the enum unmarked to indicate package-private
} else {
code += "public ";
}
- auto class_name = GenTypeName_ObjectAPI(struct_def.name, opts);
+ const auto class_name = namer_.ObjectType(struct_def);
code += "class " + class_name;
code += " {\n";
// Generate Properties
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
if (field.value.type.element == BASE_TYPE_UTYPE) continue;
- auto type_name =
- GenTypeGet_ObjectAPI(field.value.type, opts, false, true);
+ auto type_name = GenTypeGet_ObjectAPI(field.value.type, false, true);
if (field.IsScalarOptional())
type_name = ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(type_name);
- auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
- code += " private " + type_name + " " + camel_name + ";\n";
+ const auto field_name = namer_.Field(field);
+ code += " private " + type_name + " " + field_name + ";\n";
}
// Generate Java getters and setters
code += "\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
if (field.value.type.element == BASE_TYPE_UTYPE) continue;
- auto type_name =
- GenTypeGet_ObjectAPI(field.value.type, opts, false, true);
+ const auto field_name = namer_.Field(field);
+ const auto get_field = namer_.Method("get", field);
+ auto type_name = GenTypeGet_ObjectAPI(field.value.type, false, true);
if (field.IsScalarOptional())
type_name = ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(type_name);
- auto camel_name = ConvertCase(field.name, Case::kLowerCamel);
- code += " public " + type_name + " " +
- GenGetterFuncName_ObjectAPI(field.name) + "() { return " +
- camel_name + "; }\n\n";
+
+ code += " public " + type_name + " " + get_field + "() { return " +
+ field_name + "; }\n\n";
std::string array_validation = "";
if (field.value.type.base_type == BASE_TYPE_ARRAY) {
array_validation =
- "if (" + camel_name + " != null && " + camel_name +
+ "if (" + field_name + " != null && " + field_name +
".length == " + NumToString(field.value.type.fixed_length) + ") ";
}
- code += " public void " + GenSetterFuncName_ObjectAPI(field.name) + "(" +
- type_name + " " + camel_name + ") { " + array_validation +
- "this." + camel_name + " = " + camel_name + "; }\n\n";
+ code += " public void " + namer_.Method("set", field) + "(" + type_name +
+ " " + field_name + ") { " + array_validation + "this." +
+ field_name + " = " + field_name + "; }\n\n";
}
// Generate Constructor
code += "\n";
code += " public " + class_name + "() {\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
if (field.value.type.element == BASE_TYPE_UTYPE) continue;
- code += " this." + ConvertCase(field.name, Case::kLowerCamel) + " = ";
- auto type_name =
- GenTypeGet_ObjectAPI(field.value.type, opts, false, true);
+ const auto get_field = namer_.Method("get", field);
+
+ code += " this." + namer_.Field(field) + " = ";
+ const auto type_name =
+ GenTypeGet_ObjectAPI(field.value.type, false, true);
if (IsScalar(field.value.type.base_type)) {
if (field.IsScalarOptional()) {
code += "null;\n";
@@ -2122,15 +2117,18 @@
}
code += " }\n";
if (parser_.root_struct_def_ == &struct_def) {
+ const std::string struct_type = namer_.Type(struct_def);
code += " public static " + class_name +
" deserializeFromBinary(byte[] fbBuffer) {\n";
- code += " return " + struct_def.name + ".getRootAs" + struct_def.name +
+ code += " return " + struct_type + "." +
+ namer_.LegacyJavaMethod2("getRootAs", struct_def, "") +
"(ByteBuffer.wrap(fbBuffer)).unpack();\n";
code += " }\n";
code += " public byte[] serializeToBinary() {\n";
code += " FlatBufferBuilder fbb = new FlatBufferBuilder();\n";
- code += " " + struct_def.name + ".finish" + struct_def.name +
- "Buffer(fbb, " + struct_def.name + ".pack(fbb, this));\n";
+ code += " " + struct_type + "." +
+ namer_.LegacyJavaMethod2("finish", struct_def, "Buffer") +
+ "(fbb, " + struct_type + ".pack(fbb, this));\n";
code += " return fbb.sizedByteArray();\n";
code += " }\n";
}
@@ -2140,6 +2138,7 @@
// This tracks the current namespace used to determine if a type need to be
// prefixed by its namespace
const Namespace *cur_name_space_;
+ const IdlNamer namer_;
};
} // namespace java
diff --git a/third_party/flatbuffers/src/idl_gen_json_schema.cpp b/third_party/flatbuffers/src/idl_gen_json_schema.cpp
index 9ea37ae..5cb6a9d 100644
--- a/third_party/flatbuffers/src/idl_gen_json_schema.cpp
+++ b/third_party/flatbuffers/src/idl_gen_json_schema.cpp
@@ -24,7 +24,10 @@
namespace jsons {
-template<class T> std::string GenFullName(const T *enum_def) {
+namespace {
+
+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) {
@@ -34,15 +37,16 @@
return full_name;
}
-template<class T> std::string GenTypeRef(const T *enum_def) {
+template<class T>
+static std::string GenTypeRef(const T *enum_def) {
return "\"$ref\" : \"#/definitions/" + GenFullName(enum_def) + "\"";
}
-std::string GenType(const std::string &name) {
+static std::string GenType(const std::string &name) {
return "\"type\" : \"" + name + "\"";
}
-std::string GenType(BaseType type) {
+static std::string GenType(BaseType type) {
switch (type) {
case BASE_TYPE_BOOL: return "\"type\" : \"boolean\"";
case BASE_TYPE_CHAR:
@@ -84,13 +88,13 @@
}
}
-std::string GenBaseType(const Type &type) {
+static std::string GenBaseType(const Type &type) {
if (type.struct_def != nullptr) { return GenTypeRef(type.struct_def); }
if (type.enum_def != nullptr) { return GenTypeRef(type.enum_def); }
return GenType(type.base_type);
}
-std::string GenArrayType(const Type &type) {
+static std::string GenArrayType(const Type &type) {
std::string element_type;
if (type.struct_def != nullptr) {
element_type = GenTypeRef(type.struct_def);
@@ -103,7 +107,7 @@
return "\"type\" : \"array\", \"items\" : {" + element_type + "}";
}
-std::string GenType(const Type &type) {
+static std::string GenType(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_VECTOR: {
@@ -136,6 +140,8 @@
}
}
+} // namespace
+
class JsonSchemaGenerator : public BaseGenerator {
private:
std::string code_;
diff --git a/third_party/flatbuffers/src/idl_gen_kotlin.cpp b/third_party/flatbuffers/src/idl_gen_kotlin.cpp
index fc55aeb..102e24d 100644
--- a/third_party/flatbuffers/src/idl_gen_kotlin.cpp
+++ b/third_party/flatbuffers/src/idl_gen_kotlin.cpp
@@ -23,11 +23,14 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
namespace kotlin {
+namespace {
+
typedef std::map<std::string, std::pair<std::string, std::string> > FbbParamMap;
static TypedFloatConstantGenerator KotlinFloatGen("Double.", "Float.", "NaN",
"POSITIVE_INFINITY",
@@ -35,42 +38,54 @@
static const CommentConfig comment_config = { "/**", " *", " */" };
static const std::string ident_pad = " ";
-static const char *keywords[] = {
- "package", "as", "typealias", "class", "this", "super",
- "val", "var", "fun", "for", "null", "true",
- "false", "is", "in", "throw", "return", "break",
- "continue", "object", "if", "try", "else", "while",
- "do", "when", "interface", "typeof", "Any", "Character"
-};
-
-// Escape Keywords
-static std::string Esc(const std::string &name) {
- for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
- if (name == keywords[i]) {
- return ConvertCase(name + "_", Case::kLowerCamel);
- }
- }
-
- return ConvertCase(name, Case::kLowerCamel);
+static std::set<std::string> KotlinKeywords() {
+ return { "package", "as", "typealias", "class", "this", "super",
+ "val", "var", "fun", "for", "null", "true",
+ "false", "is", "in", "throw", "return", "break",
+ "continue", "object", "if", "try", "else", "while",
+ "do", "when", "interface", "typeof", "Any", "Character" };
}
+static Namer::Config KotlinDefaultConfig() {
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kKeep,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kKeep,
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kLowerCamel,
+ /*enum_variant_seperator=*/"", // I.e. Concatenate.
+ /*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"__",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"",
+ /*filename_extension=*/".kt" };
+}
+} // namespace
+
class KotlinGenerator : public BaseGenerator {
public:
KotlinGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", ".", "kt"),
- cur_name_space_(nullptr) {}
+ namer_(WithFlagOptions(KotlinDefaultConfig(), parser.opts, path),
+ KotlinKeywords()) {}
KotlinGenerator &operator=(const KotlinGenerator &);
bool generate() FLATBUFFERS_OVERRIDE {
std::string one_file_code;
- cur_name_space_ = parser_.current_namespace_;
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
CodeWriter enumWriter(ident_pad);
auto &enum_def = **it;
- if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
GenEnum(enum_def, enumWriter);
if (parser_.opts.one_file) {
one_file_code += enumWriter.ToString();
@@ -85,8 +100,6 @@
it != parser_.structs_.vec.end(); ++it) {
CodeWriter structWriter(ident_pad);
auto &struct_def = **it;
- if (!parser_.opts.one_file)
- cur_name_space_ = struct_def.defined_namespace;
GenStruct(struct_def, structWriter, parser_.opts);
if (parser_.opts.one_file) {
one_file_code += structWriter.ToString();
@@ -124,14 +137,13 @@
code += "import com.google.flatbuffers.*\n\n";
}
code += classcode;
- auto filename = NamespaceDir(ns) + defname + ".kt";
+ const std::string dirs = namer_.Directories(ns);
+ EnsureDirExists(dirs);
+ const std::string filename =
+ dirs + namer_.File(defname, /*skips=*/SkipFile::Suffix);
return SaveFile(filename.c_str(), code, false);
}
- const Namespace *CurrentNameSpace() const FLATBUFFERS_OVERRIDE {
- return cur_name_space_;
- }
-
static bool IsEnum(const Type &type) {
return type.enum_def != nullptr && IsInteger(type.base_type);
}
@@ -261,7 +273,7 @@
GenerateComment(enum_def.doc_comment, writer, &comment_config);
writer += "@Suppress(\"unused\")";
- writer += "class " + Esc(enum_def.name) + " private constructor() {";
+ writer += "class " + namer_.Type(enum_def) + " private constructor() {";
writer.IncrementIdentLevel();
GenerateCompanionObject(writer, [&]() {
@@ -272,7 +284,7 @@
auto field_type = GenTypeBasic(enum_def.underlying_type.base_type);
auto val = enum_def.ToString(ev);
auto suffix = LiteralSuffix(enum_def.underlying_type.base_type);
- writer.SetValue("name", Esc(ev.name));
+ writer.SetValue("name", namer_.LegacyKotlinVariant(ev));
writer.SetValue("type", field_type);
writer.SetValue("val", val + suffix);
GenerateComment(ev.doc_comment, writer, &comment_config);
@@ -339,8 +351,8 @@
case BASE_TYPE_UTYPE: return bb_var_name + ".get";
case BASE_TYPE_BOOL: return "0.toByte() != " + bb_var_name + ".get";
default:
- return bb_var_name + ".get" +
- ConvertCase(GenTypeBasic(type.base_type), Case::kUpperCamel);
+ return bb_var_name + "." +
+ namer_.Method("get", GenTypeBasic(type.base_type));
}
}
@@ -361,8 +373,7 @@
case BASE_TYPE_NONE:
case BASE_TYPE_UTYPE: return "bb.put";
default:
- return "bb.put" +
- ConvertCase(GenTypeBasic(type.base_type), Case::kUpperCamel);
+ return "bb." + namer_.Method("put", GenTypeBasic(type.base_type));
}
}
return "";
@@ -385,8 +396,8 @@
// Recursively generate arguments for a constructor, to deal with nested
// structs.
- static void GenStructArgs(const StructDef &struct_def, CodeWriter &writer,
- const char *nameprefix) {
+ void GenStructArgs(const StructDef &struct_def, CodeWriter &writer,
+ const char *nameprefix) const {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
@@ -399,7 +410,7 @@
(nameprefix + (field.name + "_")).c_str());
} else {
writer += std::string(", ") + nameprefix + "\\";
- writer += ConvertCase(field.name, Case::kUpperCamel) + ": \\";
+ writer += namer_.Field(field) + ": \\";
writer += GenTypeBasic(field.value.type.base_type) + "\\";
}
}
@@ -408,8 +419,8 @@
// Recusively generate struct construction statements of the form:
// builder.putType(name);
// and insert manual padding.
- static void GenStructBody(const StructDef &struct_def, CodeWriter &writer,
- const char *nameprefix) {
+ void GenStructBody(const StructDef &struct_def, CodeWriter &writer,
+ const char *nameprefix) const {
writer.SetValue("align", NumToString(struct_def.minalign));
writer.SetValue("size", NumToString(struct_def.bytesize));
writer += "builder.prep({{align}}, {{size}})";
@@ -426,8 +437,7 @@
(nameprefix + (field.name + "_")).c_str());
} else {
writer.SetValue("type", GenMethod(field.value.type));
- writer.SetValue("argname", nameprefix + ConvertCase(Esc(field.name),
- Case::kLowerCamel));
+ writer.SetValue("argname", nameprefix + namer_.Variable(field));
writer.SetValue("cast", CastToSigned(field.value.type));
writer += "builder.put{{type}}({{argname}}{{cast}})";
}
@@ -461,7 +471,7 @@
GenerateComment(struct_def.doc_comment, writer, &comment_config);
auto fixed = struct_def.fixed;
- writer.SetValue("struct_name", Esc(struct_def.name));
+ writer.SetValue("struct_name", namer_.Type(struct_def));
writer.SetValue("superclass", fixed ? "Struct" : "Table");
writer += "@Suppress(\"unused\")";
@@ -477,7 +487,7 @@
// Generate assign method
GenerateFun(writer, "__assign", "_i: Int, _bb: ByteBuffer",
- Esc(struct_def.name), [&]() {
+ namer_.Type(struct_def), [&]() {
writer += "__init(_i, _bb)";
writer += "return this";
});
@@ -490,15 +500,15 @@
if (!struct_def.fixed) {
FieldDef *key_field = nullptr;
- // Generate verson check method.
+ // Generate version check method.
// Force compile time error if not using the same version
// runtime.
GenerateFunOneLine(
writer, "validateVersion", "", "",
- [&]() { writer += "Constants.FLATBUFFERS_2_0_0()"; },
+ [&]() { writer += "Constants.FLATBUFFERS_2_0_8()"; },
options.gen_jvmstatic);
- GenerateGetRootAsAccessors(Esc(struct_def.name), writer, options);
+ GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options);
GenerateBufferHasIdentifier(struct_def, writer, options);
GenerateTableCreator(struct_def, writer, options);
@@ -550,7 +560,7 @@
void GenerateLookupByKey(FieldDef *key_field, StructDef &struct_def,
CodeWriter &writer, const IDLOptions options) const {
std::stringstream params;
- params << "obj: " << Esc(struct_def.name) << "?"
+ params << "obj: " << namer_.Type(struct_def) << "?"
<< ", ";
params << "vectorLocation: Int, ";
params << "key: " << GenTypeGet(key_field->value.type) << ", ";
@@ -558,7 +568,7 @@
auto statements = [&]() {
auto base_type = key_field->value.type.base_type;
- writer.SetValue("struct_name", Esc(struct_def.name));
+ writer.SetValue("struct_name", namer_.Type(struct_def));
if (base_type == BASE_TYPE_STRING) {
writer +=
"val byteKey = key."
@@ -604,7 +614,8 @@
writer += "return null";
};
GenerateFun(writer, "__lookup_by_key", params.str(),
- Esc(struct_def.name) + "?", statements, options.gen_jvmstatic);
+ namer_.Type(struct_def) + "?", statements,
+ options.gen_jvmstatic);
}
void GenerateFinishSizePrefixed(StructDef &struct_def,
@@ -613,7 +624,8 @@
const IDLOptions options) const {
auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : "";
auto params = "builder: FlatBufferBuilder, offset: Int";
- auto method_name = "finishSizePrefixed" + Esc(struct_def.name) + "Buffer";
+ auto method_name =
+ namer_.LegacyJavaMethod2("finishSizePrefixed", struct_def, "Buffer");
GenerateFunOneLine(
writer, method_name, params, "",
[&]() { writer += "builder.finishSizePrefixed(offset" + id + ")"; },
@@ -625,7 +637,8 @@
const IDLOptions options) const {
auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : "";
auto params = "builder: FlatBufferBuilder, offset: Int";
- auto method_name = "finish" + Esc(struct_def.name) + "Buffer";
+ auto method_name =
+ namer_.LegacyKotlinMethod("finish", struct_def, "Buffer");
GenerateFunOneLine(
writer, method_name, params, "",
[&]() { writer += "builder.finish(offset" + id + ")"; },
@@ -635,7 +648,7 @@
void GenerateEndStructMethod(StructDef &struct_def, CodeWriter &writer,
const IDLOptions options) const {
// Generate end{{TableName}}(builder: FlatBufferBuilder) method
- auto name = "end" + Esc(struct_def.name);
+ auto name = namer_.LegacyJavaMethod2("end", struct_def, "");
auto params = "builder: FlatBufferBuilder";
auto returns = "Int";
auto field_vec = struct_def.fields.vec;
@@ -661,8 +674,7 @@
void GenerateCreateVectorField(FieldDef &field, CodeWriter &writer,
const IDLOptions options) const {
auto vector_type = field.value.type.VectorType();
- auto method_name =
- "create" + ConvertCase(Esc(field.name), Case::kUpperCamel) + "Vector";
+ auto method_name = namer_.Method("create", field, "vector");
auto params = "builder: FlatBufferBuilder, data: " +
GenTypeBasic(vector_type.base_type) + "Array";
writer.SetValue("size", NumToString(InlineSize(vector_type)));
@@ -694,9 +706,7 @@
writer.SetValue("align", NumToString(InlineAlignment(vector_type)));
GenerateFunOneLine(
- writer,
- "start" + ConvertCase(Esc(field.name) + "Vector", Case::kUpperCamel),
- params, "",
+ writer, namer_.Method("start", field, "Vector"), params, "",
[&]() {
writer += "builder.startVector({{size}}, numElems, {{align}})";
},
@@ -706,25 +716,36 @@
void GenerateAddField(std::string field_pos, FieldDef &field,
CodeWriter &writer, const IDLOptions options) const {
auto field_type = GenTypeBasic(field.value.type.base_type);
- auto secondArg =
- ConvertCase(Esc(field.name), Case::kLowerCamel) + ": " + field_type;
+ auto secondArg = namer_.Variable(field.name) + ": " + field_type;
- GenerateFunOneLine(
- writer, "add" + ConvertCase(Esc(field.name), Case::kUpperCamel),
- "builder: FlatBufferBuilder, " + secondArg, "",
- [&]() {
- auto method = GenMethod(field.value.type);
- writer.SetValue("field_name",
- ConvertCase(Esc(field.name), Case::kLowerCamel));
- writer.SetValue("method_name", method);
- writer.SetValue("pos", field_pos);
- writer.SetValue("default", GenFBBDefaultValue(field));
- writer.SetValue("cast", GenFBBValueCast(field));
-
- writer += "builder.add{{method_name}}({{pos}}, \\";
- writer += "{{field_name}}{{cast}}, {{default}})";
- },
- options.gen_jvmstatic);
+ auto content = [&]() {
+ auto method = GenMethod(field.value.type);
+ writer.SetValue("field_name", namer_.Field(field));
+ writer.SetValue("method_name", method);
+ writer.SetValue("pos", field_pos);
+ writer.SetValue("default", GenFBBDefaultValue(field));
+ writer.SetValue("cast", GenFBBValueCast(field));
+ if (field.key) {
+ // field has key attribute, so always need to exist
+ // even if its value is equal to default.
+ // Generated code will bypass default checking
+ // resulting in { builder.addShort(name); slot(id); }
+ writer += "builder.add{{method_name}}({{field_name}}{{cast}})";
+ writer += "builder.slot({{pos}})";
+ } else {
+ writer += "builder.add{{method_name}}({{pos}}, \\";
+ writer += "{{field_name}}{{cast}}, {{default}})";
+ }
+ };
+ auto signature = namer_.LegacyKotlinMethod("add", field, "");
+ auto params = "builder: FlatBufferBuilder, " + secondArg;
+ if (field.key) {
+ GenerateFun(writer, signature, params, "", content,
+ options.gen_jvmstatic);
+ } else {
+ GenerateFunOneLine(writer, signature, params, "", content,
+ options.gen_jvmstatic);
+ }
}
static std::string ToSignedType(const Type &type) {
@@ -768,7 +789,8 @@
void GenerateStartStructMethod(StructDef &struct_def, CodeWriter &code,
const IDLOptions options) const {
GenerateFunOneLine(
- code, "start" + Esc(struct_def.name), "builder: FlatBufferBuilder", "",
+ code, namer_.LegacyJavaMethod2("start", struct_def, ""),
+ "builder: FlatBufferBuilder", "",
[&]() {
code += "builder.startTable(" +
NumToString(struct_def.fields.vec.size()) + ")";
@@ -800,13 +822,13 @@
// Generate a table constructor of the form:
// public static int createName(FlatBufferBuilder builder, args...)
- auto name = "create" + Esc(struct_def.name);
+ auto name = namer_.LegacyJavaMethod2("create", struct_def, "");
std::stringstream params;
params << "builder: FlatBufferBuilder";
for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- params << ", " << ConvertCase(Esc(field.name), Case::kLowerCamel);
+ params << ", " << namer_.Variable(field);
if (!IsScalar(field.value.type.base_type)) {
params << "Offset: ";
} else {
@@ -832,18 +854,15 @@
auto base_type_size = SizeOf(field.value.type.base_type);
if (!field.deprecated &&
(!sortbysize || size == base_type_size)) {
- writer.SetValue(
- "camel_field_name",
- ConvertCase(Esc(field.name), Case::kUpperCamel));
- writer.SetValue("field_name", ConvertCase(Esc(field.name),
- Case::kLowerCamel));
+ writer.SetValue("field_name", namer_.Field(field));
// we wrap on null check for scalar optionals
writer += field.IsScalarOptional()
? "{{field_name}}?.run { \\"
: "\\";
- writer += "add{{camel_field_name}}(builder, {{field_name}}\\";
+ writer += namer_.LegacyKotlinMethod("add", field, "") +
+ "(builder, {{field_name}}\\";
if (!IsScalar(field.value.type.base_type)) {
writer += "Offset\\";
}
@@ -863,7 +882,7 @@
// Check if a buffer has the identifier.
if (parser_.root_struct_def_ != &struct_def || !file_identifier.length())
return;
- auto name = ConvertCase(Esc(struct_def.name), Case::kLowerCamel);
+ auto name = namer_.Function(struct_def);
GenerateFunOneLine(
writer, name + "BufferHasIdentifier", "_bb: ByteBuffer", "Boolean",
[&]() {
@@ -882,7 +901,7 @@
GenerateComment(field.doc_comment, writer, &comment_config);
- auto field_name = ConvertCase(Esc(field.name), Case::kLowerCamel);
+ auto field_name = namer_.Field(field);
auto field_type = GenTypeGet(field.value.type);
auto field_default_value = GenDefaultValue(field);
auto return_type = GetterReturnType(field);
@@ -1053,8 +1072,7 @@
auto &kfield = **kit;
if (kfield.key) {
auto qualified_name = WrapInNameSpace(sd);
- auto name =
- ConvertCase(Esc(field.name), Case::kLowerCamel) + "ByKey";
+ auto name = namer_.Method(field, "ByKey");
auto params = "key: " + GenTypeGet(kfield.value.type);
auto rtype = qualified_name + "?";
GenerateFun(writer, name, params, rtype, [&]() {
@@ -1147,9 +1165,9 @@
auto underlying_type = value_base_type == BASE_TYPE_VECTOR
? value_type.VectorType()
: value_type;
- auto name = "mutate" + ConvertCase(Esc(field.name), Case::kUpperCamel);
+ auto name = namer_.LegacyKotlinMethod("mutate", field, "");
auto size = NumToString(InlineSize(underlying_type));
- auto params = Esc(field.name) + ": " + GenTypeGet(underlying_type);
+ auto params = namer_.Field(field) + ": " + GenTypeGet(underlying_type);
// A vector mutator also needs the index of the vector element it should
// mutate.
if (value_base_type == BASE_TYPE_VECTOR) params.insert(0, "j: Int, ");
@@ -1158,8 +1176,8 @@
// representation.
auto setter_parameter =
underlying_type.base_type == BASE_TYPE_BOOL
- ? "(if(" + Esc(field.name) + ") 1 else 0).toByte()"
- : Esc(field.name);
+ ? "(if(" + namer_.Field(field) + ") 1 else 0).toByte()"
+ : namer_.Field(field);
auto setter_index =
value_base_type == BASE_TYPE_VECTOR
@@ -1292,9 +1310,9 @@
}
}
- static void GenerateGetRootAsAccessors(const std::string &struct_name,
- CodeWriter &writer,
- IDLOptions options) {
+ void GenerateGetRootAsAccessors(const std::string &struct_name,
+ CodeWriter &writer,
+ IDLOptions options) const {
// Generate a special accessor for the table that when used as the root
// ex: fun getRootAsMonster(_bb: ByteBuffer): Monster {...}
writer.SetValue("gr_name", struct_name);
@@ -1320,13 +1338,12 @@
writer += "}";
}
- static void GenerateStaticConstructor(const StructDef &struct_def,
- CodeWriter &code,
- const IDLOptions options) {
+ void GenerateStaticConstructor(const StructDef &struct_def, CodeWriter &code,
+ const IDLOptions options) const {
// create a struct constructor function
auto params = StructConstructorParams(struct_def);
GenerateFun(
- code, "create" + Esc(struct_def.name), params, "Int",
+ code, namer_.LegacyJavaMethod2("create", struct_def, ""), params, "Int",
[&]() {
GenStructBody(struct_def, code, "");
code += "return builder.offset()";
@@ -1334,8 +1351,8 @@
options.gen_jvmstatic);
}
- static std::string StructConstructorParams(const StructDef &struct_def,
- const std::string &prefix = "") {
+ std::string StructConstructorParams(const StructDef &struct_def,
+ const std::string &prefix = "") const {
// builder: FlatBufferBuilder
std::stringstream out;
auto field_vec = struct_def.fields.vec;
@@ -1348,10 +1365,10 @@
// constructing a nested struct, prefix the name with the field
// name.
out << StructConstructorParams(*field.value.type.struct_def,
- prefix + (Esc(field.name) + "_"));
+ prefix + (namer_.Variable(field) + "_"));
} else {
- out << ", " << prefix << ConvertCase(Esc(field.name), Case::kLowerCamel)
- << ": " << GenTypeBasic(field.value.type.base_type);
+ out << ", " << prefix << namer_.Variable(field) << ": "
+ << GenTypeBasic(field.value.type.base_type);
}
}
return out.str();
@@ -1520,9 +1537,7 @@
if (gen_jvmstatic) { code += "@JvmStatic"; }
}
- // This tracks the current namespace used to determine if a type need to be
- // prefixed by its namespace
- const Namespace *cur_name_space_;
+ const IdlNamer namer_;
};
} // namespace kotlin
diff --git a/third_party/flatbuffers/src/idl_gen_lobster.cpp b/third_party/flatbuffers/src/idl_gen_lobster.cpp
index c1e78ad..67830f3 100644
--- a/third_party/flatbuffers/src/idl_gen_lobster.cpp
+++ b/third_party/flatbuffers/src/idl_gen_lobster.cpp
@@ -72,9 +72,11 @@
std::string LobsterType(const Type &type) {
if (IsFloat(type.base_type)) return "float";
+ if (IsBool(type.base_type)) return "bool";
if (IsScalar(type.base_type) && type.enum_def)
return NormalizedName(*type.enum_def);
if (!IsScalar(type.base_type)) return "flatbuffers_offset";
+ if (IsString(type)) return "string";
return "int";
}
@@ -116,21 +118,27 @@
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 (field.value.type.enum_def)
acc = NormalizedName(*field.value.type.enum_def) + "(" + acc + ")";
- if (field.IsOptional())
+ if (field.IsOptional()) {
acc += ", buf_.flatbuffers_field_present(pos_, " + offsets + ")";
- code += def + "():\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";
+ }
return;
}
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
auto name = NamespacedName(*field.value.type.struct_def);
- code += def + "():\n ";
if (struct_def.fixed) {
+ code += def + "() -> " + name + ":\n ";
code += "return " + name + "{ buf_, pos_ + " + offsets + " }\n";
} else {
+ code += def + "() -> " + name + "?:\n ";
code += std::string("let o = buf_.flatbuffers_field_") +
(field.value.type.struct_def->fixed ? "struct" : "table") +
"(pos_, " + offsets + ")\n return if o: " + name +
@@ -140,25 +148,28 @@
}
case BASE_TYPE_STRING:
code += def +
- "():\n return buf_.flatbuffers_field_string(pos_, " +
+ "() -> string:\n return buf_.flatbuffers_field_string(pos_, " +
offsets + ")\n";
break;
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
- code += def + "(i:int):\n return ";
if (vectortype.base_type == BASE_TYPE_STRUCT) {
auto start = "buf_.flatbuffers_field_vector(pos_, " + offsets +
") + i * " + NumToString(InlineSize(vectortype));
if (!(vectortype.struct_def->fixed)) {
start = "buf_.flatbuffers_indirect(" + start + ")";
}
+ code += def + "(i:int) -> " + NamespacedName(*field.value.type.struct_def) + ":\n return ";
code += NamespacedName(*field.value.type.struct_def) + " { buf_, " +
start + " }\n";
} else {
- if (IsString(vectortype))
+ if (IsString(vectortype)) {
+ code += def + "(i:int) -> string:\n return ";
code += "buf_.flatbuffers_string";
- else
+ } else {
+ code += def + "(i:int) -> " + LobsterType(vectortype) + ":\n return ";
code += "buf_.read_" + GenTypeName(vectortype) + "_le";
+ }
code += "(buf_.flatbuffers_field_vector(pos_, " + offsets +
") + i * " + NumToString(InlineSize(vectortype)) + ")\n";
}
@@ -181,7 +192,7 @@
}
if (IsVector(field.value.type)) {
code += def +
- "_length():\n return "
+ "_length() -> int:\n return "
"buf_.flatbuffers_field_vector_len(pos_, " +
offsets + ")\n";
}
diff --git a/third_party/flatbuffers/src/idl_gen_python.cpp b/third_party/flatbuffers/src/idl_gen_python.cpp
index 8426b6e..0b8ffa8 100644
--- a/third_party/flatbuffers/src/idl_gen_python.cpp
+++ b/third_party/flatbuffers/src/idl_gen_python.cpp
@@ -26,12 +26,14 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
-#include "namer.h"
+#include "idl_namer.h"
namespace flatbuffers {
namespace python {
-std::set<std::string> PythonKeywords() {
+namespace {
+
+static std::set<std::string> PythonKeywords() {
return { "False", "None", "True", "and", "as", "assert",
"break", "class", "continue", "def", "del", "elif",
"else", "except", "finally", "for", "from", "global",
@@ -40,7 +42,7 @@
"while", "with", "yield" };
}
-Namer::Config PythonDefaultConfig() {
+static Namer::Config PythonDefaultConfig() {
return { /*types=*/Case::kKeep,
/*constants=*/Case::kScreamingSnake,
/*methods=*/Case::kUpperCamel,
@@ -49,6 +51,7 @@
/*variable=*/Case::kLowerCamel,
/*variants=*/Case::kKeep,
/*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
/*namespaces=*/Case::kKeep, // Packages in python.
/*namespace_seperator=*/".",
/*object_prefix=*/"",
@@ -63,8 +66,10 @@
}
// Hardcode spaces per indentation.
-const CommentConfig def_comment = { nullptr, "#", nullptr };
-const std::string Indent = " ";
+static const CommentConfig def_comment = { nullptr, "#", nullptr };
+static const std::string Indent = " ";
+
+} // namespace
class PythonGenerator : public BaseGenerator {
public:
@@ -73,8 +78,8 @@
: BaseGenerator(parser, path, file_name, "" /* not used */,
"" /* not used */, "py"),
float_const_gen_("float('nan')", "float('inf')", "float('-inf')"),
- namer_({ PythonDefaultConfig().WithFlagOptions(parser.opts, path),
- PythonKeywords() }) {}
+ namer_(WithFlagOptions(PythonDefaultConfig(), parser.opts, path),
+ PythonKeywords()) {}
// Most field accessors need to retrieve and test the field offset first,
// this is the prefix code for that.
@@ -88,7 +93,7 @@
// Begin a class declaration.
void BeginClass(const StructDef &struct_def, std::string *code_ptr) const {
auto &code = *code_ptr;
- code += "class " + namer_.Type(struct_def.name) + "(object):\n";
+ code += "class " + namer_.Type(struct_def) + "(object):\n";
code += Indent + "__slots__ = ['_tab']";
code += "\n\n";
}
@@ -96,7 +101,7 @@
// Begin enum code with a class declaration.
void BeginEnum(const EnumDef &enum_def, std::string *code_ptr) const {
auto &code = *code_ptr;
- code += "class " + namer_.Type(enum_def.name) + "(object):\n";
+ code += "class " + namer_.Type(enum_def) + "(object):\n";
}
// Starts a new line and then indents.
@@ -109,7 +114,7 @@
std::string *code_ptr) const {
auto &code = *code_ptr;
code += Indent;
- code += namer_.Variant(ev.name);
+ code += namer_.Variant(ev);
code += " = ";
code += enum_def.ToString(ev) + "\n";
}
@@ -118,7 +123,7 @@
void NewRootTypeFromBuffer(const StructDef &struct_def,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const std::string struct_type = namer_.Type(struct_def.name);
+ const std::string struct_type = namer_.Type(struct_def);
code += Indent + "@classmethod\n";
code += Indent + "def GetRootAs";
@@ -158,7 +163,7 @@
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name) + "Length(self";
+ code += namer_.Method(field) + "Length(self";
code += "):" + OffsetPrefix(field);
code += Indent + Indent + Indent + "return self._tab.VectorLen(o)\n";
code += Indent + Indent + "return 0\n\n";
@@ -170,7 +175,7 @@
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name) + "IsNone(self";
+ code += namer_.Method(field) + "IsNone(self";
code += "):";
code += GenIndents(2) +
"o = flatbuffers.number_types.UOffsetTFlags.py_type" +
@@ -186,7 +191,7 @@
auto &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name);
+ code += namer_.Method(field);
code += "(self): return " + getter;
code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
code += NumToString(field.value.offset) + "))\n";
@@ -198,7 +203,7 @@
auto &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name);
+ code += namer_.Method(field);
code += "(self):";
code += OffsetPrefix(field);
getter += "o + self._tab.Pos)";
@@ -206,7 +211,9 @@
if (is_bool) { getter = "bool(" + getter + ")"; }
code += Indent + Indent + Indent + "return " + getter + "\n";
std::string default_value;
- if (is_bool) {
+ if (field.IsScalarOptional()) {
+ default_value = "None";
+ } else if (is_bool) {
default_value = field.value.constant == "0" ? "False" : "True";
} else {
default_value = IsFloat(field.value.type.base_type)
@@ -223,7 +230,7 @@
std::string *code_ptr) const {
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name);
+ code += namer_.Method(field);
code += "(self, obj):\n";
code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
code += NumToString(field.value.offset) + ")";
@@ -236,7 +243,7 @@
auto &code = *code_ptr;
const auto vec_type = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name);
+ code += namer_.Method(field);
if (IsStruct(vec_type)) {
code += "(self, obj, i):\n";
code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
@@ -260,7 +267,7 @@
std::string *code_ptr) const {
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name);
+ code += namer_.Method(field);
code += "(self):";
code += OffsetPrefix(field);
if (field.value.type.struct_def->fixed) {
@@ -285,7 +292,7 @@
std::string *code_ptr) const {
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name);
+ code += namer_.Method(field);
code += "(self):";
code += OffsetPrefix(field);
code += Indent + Indent + Indent + "return " + GenGetter(field.value.type);
@@ -298,7 +305,7 @@
std::string *code_ptr) const {
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name) + "(self):";
+ code += namer_.Method(field) + "(self):";
code += OffsetPrefix(field);
// TODO(rw): this works and is not the good way to it:
@@ -321,21 +328,13 @@
// module.
std::string GenPackageReference(const Type &type) const {
if (type.struct_def) {
- return GenPackageReference(*type.struct_def);
+ return namer_.NamespacedType(*type.struct_def);
} else if (type.enum_def) {
- return GenPackageReference(*type.enum_def);
+ return namer_.NamespacedType(*type.enum_def);
} else {
return "." + GenTypeGet(type);
}
}
- std::string GenPackageReference(const EnumDef &enum_def) const {
- return namer_.NamespacedType(enum_def.defined_namespace->components,
- enum_def.name);
- }
- std::string GenPackageReference(const StructDef &struct_def) const {
- return namer_.NamespacedType(struct_def.defined_namespace->components,
- struct_def.name);
- }
// Get the value of a vector's struct member.
void GetMemberOfVectorOfStruct(const StructDef &struct_def,
@@ -345,7 +344,7 @@
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name);
+ code += namer_.Method(field);
code += "(self, j):" + OffsetPrefix(field);
code += Indent + Indent + Indent + "x = self._tab.Vector(o)\n";
code += Indent + Indent + Indent;
@@ -374,7 +373,7 @@
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name);
+ code += namer_.Method(field);
code += "(self, j):";
code += OffsetPrefix(field);
code += Indent + Indent + Indent + "a = self._tab.Vector(o)\n";
@@ -403,7 +402,7 @@
if (!(IsScalar(vectortype.base_type))) { return; }
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name) + "AsNumpy(self):";
+ code += namer_.Method(field) + "AsNumpy(self):";
code += OffsetPrefix(field);
code += Indent + Indent + Indent;
@@ -421,7 +420,7 @@
}
std::string NestedFlatbufferType(std::string unqualified_name) const {
- StructDef* nested_root = parser_.LookupStruct(unqualified_name);
+ StructDef *nested_root = parser_.LookupStruct(unqualified_name);
std::string qualified_name;
if (nested_root == nullptr) {
qualified_name = namer_.NamespacedType(
@@ -445,7 +444,7 @@
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += namer_.Method(field.name) + "NestedRoot(self):";
+ code += namer_.Method(field) + "NestedRoot(self):";
code += OffsetPrefix(field);
@@ -464,7 +463,7 @@
auto &code = *code_ptr;
code += "\n";
- code += "def Create" + namer_.Type(struct_def.name);
+ code += "def Create" + namer_.Type(struct_def);
code += "(builder";
}
@@ -487,14 +486,14 @@
// a nested struct, prefix the name with the field name.
auto subprefix = nameprefix;
if (has_field_name) {
- subprefix += namer_.Field(field.name) + fieldname_suffix;
+ subprefix += namer_.Field(field) + fieldname_suffix;
}
StructBuilderArgs(*field.value.type.struct_def, subprefix, namesuffix,
has_field_name, fieldname_suffix, code_ptr);
} else {
auto &code = *code_ptr;
code += std::string(", ") + nameprefix;
- if (has_field_name) { code += namer_.Field(field.name); }
+ if (has_field_name) { code += namer_.Field(field); }
code += namesuffix;
}
}
@@ -526,10 +525,9 @@
code +=
indent + " builder.Pad(" + NumToString(field.padding) + ")\n";
if (IsStruct(field_type)) {
- StructBuilderBody(
- *field_type.struct_def,
- (nameprefix + (namer_.Field(field.name) + "_")).c_str(), code_ptr,
- index, in_array);
+ StructBuilderBody(*field_type.struct_def,
+ (nameprefix + (namer_.Field(field) + "_")).c_str(),
+ code_ptr, index, in_array);
} else {
const auto index_var = "_idx" + NumToString(index);
if (IsArray(field_type)) {
@@ -539,14 +537,13 @@
in_array = true;
}
if (IsStruct(type)) {
- StructBuilderBody(
- *field_type.struct_def,
- (nameprefix + (namer_.Field(field.name) + "_")).c_str(), code_ptr,
- index + 1, in_array);
+ StructBuilderBody(*field_type.struct_def,
+ (nameprefix + (namer_.Field(field) + "_")).c_str(),
+ code_ptr, index + 1, in_array);
} else {
code += IsArray(field_type) ? " " : "";
code += indent + " builder.Prepend" + GenMethod(field) + "(";
- code += nameprefix + namer_.Variable(field.name);
+ code += nameprefix + namer_.Variable(field);
size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
for (size_t i = 0; in_array && i < array_cnt; i++) {
code += "[_idx" + NumToString(i) + "-1]";
@@ -566,7 +563,7 @@
void GetStartOfTable(const StructDef &struct_def,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto struct_type = namer_.Type(struct_def.name);
+ const auto struct_type = namer_.Type(struct_def);
// Generate method with struct name.
code += "def " + struct_type + "Start(builder): ";
code += "builder.StartObject(";
@@ -584,11 +581,11 @@
void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
const size_t offset, std::string *code_ptr) const {
auto &code = *code_ptr;
- const std::string field_var = namer_.Variable(field.name);
- const std::string field_method = namer_.Method(field.name);
+ const std::string field_var = namer_.Variable(field);
+ const std::string field_method = namer_.Method(field);
// Generate method with struct name.
- code += "def " + namer_.Type(struct_def.name) + "Add" + field_method;
+ code += "def " + namer_.Type(struct_def) + "Add" + field_method;
code += "(builder, ";
code += field_var;
code += "): ";
@@ -602,16 +599,20 @@
code += field_var;
}
code += ", ";
- code += IsFloat(field.value.type.base_type)
- ? float_const_gen_.GenFloatConstant(field)
- : field.value.constant;
+ if (field.IsScalarOptional()) {
+ code += "None";
+ } else if (IsFloat(field.value.type.base_type)) {
+ code += float_const_gen_.GenFloatConstant(field);
+ } else {
+ code += field.value.constant;
+ }
code += ")\n";
if (!parser_.opts.one_file) {
// Generate method without struct name.
code += "def Add" + field_method + "(builder, " + field_var + "):\n";
- code += Indent + "return " + namer_.Type(struct_def.name) + "Add" +
- field_method;
+ code +=
+ Indent + "return " + namer_.Type(struct_def) + "Add" + field_method;
code += "(builder, ";
code += field_var;
code += ")\n";
@@ -622,8 +623,8 @@
void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const std::string struct_type = namer_.Type(struct_def.name);
- const std::string field_method = namer_.Method(field.name);
+ const std::string struct_type = namer_.Type(struct_def);
+ const std::string field_method = namer_.Method(field);
// Generate method with struct name.
code += "def " + struct_type + "Start" + field_method;
@@ -653,8 +654,8 @@
if (!nested) { return; } // There is no nested flatbuffer.
auto &code = *code_ptr;
- const std::string field_method = namer_.Method(field.name);
- const std::string struct_type = namer_.Type(struct_def.name);
+ const std::string field_method = namer_.Method(field);
+ const std::string struct_type = namer_.Type(struct_def);
// Generate method with struct and field name.
code += "def " + struct_type + "Make" + field_method;
@@ -685,22 +686,21 @@
auto &code = *code_ptr;
// Generate method with struct name.
- code += "def " + namer_.Type(struct_def.name) + "End";
+ code += "def " + namer_.Type(struct_def) + "End";
code += "(builder): ";
code += "return builder.EndObject()\n";
if (!parser_.opts.one_file) {
// Generate method without struct name.
code += "def End(builder):\n";
- code +=
- Indent + "return " + namer_.Type(struct_def.name) + "End(builder)";
+ code += Indent + "return " + namer_.Type(struct_def) + "End(builder)";
}
}
// Generate the receiver for function signatures.
void GenReceiver(const StructDef &struct_def, std::string *code_ptr) const {
auto &code = *code_ptr;
- code += Indent + "# " + namer_.Type(struct_def.name) + "\n";
+ code += Indent + "# " + namer_.Type(struct_def) + "\n";
code += Indent + "def ";
}
@@ -795,7 +795,7 @@
}
code += Indent + "@classmethod\n";
- code += Indent + "def " + namer_.Type(struct_def.name);
+ code += Indent + "def " + namer_.Type(struct_def);
code += "BufferHasIdentifier(cls, buf, offset, size_prefixed=False):";
code += "\n";
code += Indent + Indent;
@@ -846,7 +846,7 @@
void GenReceiverForObjectAPI(const StructDef &struct_def,
std::string *code_ptr) const {
auto &code = *code_ptr;
- code += GenIndents(1) + "# " + namer_.ObjectType(struct_def.name);
+ code += GenIndents(1) + "# " + namer_.ObjectType(struct_def);
code += GenIndents(1) + "def ";
}
@@ -854,7 +854,7 @@
std::string *code_ptr) const {
auto &code = *code_ptr;
code += "\n";
- code += "class " + namer_.ObjectType(struct_def.name) + "(object):";
+ code += "class " + namer_.ObjectType(struct_def) + "(object):";
code += "\n";
}
@@ -878,7 +878,9 @@
std::string GetDefaultValue(const FieldDef &field) const {
BaseType base_type = field.value.type.base_type;
- if (IsBool(base_type)) {
+ if (field.IsScalarOptional()) {
+ return "None";
+ } else if (IsBool(base_type)) {
return field.value.constant == "0" ? "False" : "True";
} else if (IsFloat(base_type)) {
return float_const_gen_.GenFloatConstant(field);
@@ -907,7 +909,7 @@
std::string field_type;
switch (ev.union_type.base_type) {
case BASE_TYPE_STRUCT:
- field_type = namer_.ObjectType(ev.union_type.struct_def->name);
+ field_type = namer_.ObjectType(*ev.union_type.struct_def);
if (parser_.opts.include_dependence_headers) {
auto package_reference = GenPackageReference(ev.union_type);
field_type = package_reference + "." + field_type;
@@ -927,8 +929,7 @@
// Gets the import lists for the union.
if (parser_.opts.include_dependence_headers) {
- const auto package_reference =
- GenPackageReference(*field.value.type.enum_def);
+ const auto package_reference = GenPackageReference(field.value.type);
import_list->insert("import " + package_reference);
}
}
@@ -939,7 +940,7 @@
import_typing_list->insert("Optional");
auto &output = *out_ptr;
const Type &type = field.value.type;
- const std::string object_type = namer_.ObjectType(type.struct_def->name);
+ const std::string object_type = namer_.ObjectType(*type.struct_def);
if (parser_.opts.include_dependence_headers) {
auto package_reference = GenPackageReference(type);
output = package_reference + "." + object_type + "]";
@@ -959,7 +960,7 @@
const BaseType base_type = vector_type.base_type;
if (base_type == BASE_TYPE_STRUCT) {
const std::string object_type =
- namer_.ObjectType(GenTypeGet(vector_type));
+ namer_.ObjectType(*vector_type.struct_def);
field_type = object_type + "]";
if (parser_.opts.include_dependence_headers) {
auto package_reference = GenPackageReference(vector_type);
@@ -1002,12 +1003,15 @@
default:
// Scalar or sting fields.
field_type = GetBasePythonTypeForScalarAndString(base_type);
+ if (field.IsScalarOptional()) {
+ field_type = "Optional[" + field_type + "]";
+ }
break;
}
const auto default_value = GetDefaultValue(field);
// Wrties the init statement.
- const auto field_field = namer_.Field(field.name);
+ const auto field_field = namer_.Field(field);
code += GenIndents(2) + "self." + field_field + " = " + default_value +
" # type: " + field_type;
}
@@ -1045,15 +1049,15 @@
}
// Removes the import of the struct itself, if applied.
- auto struct_import = "import " + GenPackageReference(struct_def);
+ auto struct_import = "import " + namer_.NamespacedType(struct_def);
import_list->erase(struct_import);
}
void InitializeFromBuf(const StructDef &struct_def,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto struct_var = namer_.Variable(struct_def.name);
- const auto struct_type = namer_.Type(struct_def.name);
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto struct_type = namer_.Type(struct_def);
code += GenIndents(1) + "@classmethod";
code += GenIndents(1) + "def InitFromBuf(cls, buf, pos):";
@@ -1066,8 +1070,8 @@
void InitializeFromObjForObject(const StructDef &struct_def,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto struct_var = namer_.Variable(struct_def.name);
- const auto struct_object = namer_.ObjectType(struct_def.name);
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto struct_object = namer_.ObjectType(struct_def);
code += GenIndents(1) + "@classmethod";
code += GenIndents(1) + "def InitFromObj(cls, " + struct_var + "):";
@@ -1080,9 +1084,9 @@
void GenUnPackForStruct(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto struct_var = namer_.Variable(struct_def.name);
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
auto field_type = TypeName(field);
if (parser_.opts.include_dependence_headers) {
@@ -1108,14 +1112,14 @@
void GenUnPackForUnion(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
- const auto struct_var = namer_.Variable(struct_def.name);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
const EnumDef &enum_def = *field.value.type.enum_def;
- auto union_type = namer_.Namespace(enum_def.name);
+ auto union_type = namer_.Type(enum_def);
if (parser_.opts.include_dependence_headers) {
- union_type = GenPackageReference(enum_def) + "." + union_type;
+ union_type = namer_.NamespacedType(enum_def) + "." + union_type;
}
code += GenIndents(2) + "self." + field_field + " = " + union_type +
"Creator(" + "self." + field_field + "Type, " + struct_var + "." +
@@ -1126,9 +1130,9 @@
const FieldDef &field,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
- const auto struct_var = namer_.Variable(struct_def.name);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
code += GenIndents(2) + "if not " + struct_var + "." + field_method +
"IsNone():";
@@ -1160,9 +1164,9 @@
std::string *code_ptr,
int indents) const {
auto &code = *code_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
- const auto struct_var = namer_.Variable(struct_def.name);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
code += GenIndents(indents) + "self." + field_field + " = []";
code += GenIndents(indents) + "for i in range(" + struct_var + "." +
@@ -1175,9 +1179,9 @@
const FieldDef &field,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
- const auto struct_var = namer_.Variable(struct_def.name);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
code += GenIndents(2) + "if not " + struct_var + "." + field_method +
"IsNone():";
@@ -1200,9 +1204,9 @@
void GenUnPackForScalar(const StructDef &struct_def, const FieldDef &field,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
- const auto struct_var = namer_.Variable(struct_def.name);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
code += GenIndents(2) + "self." + field_field + " = " + struct_var + "." +
field_method + "()";
@@ -1248,7 +1252,7 @@
// Writes import statements and code into the generated file.
auto &code_base = *code_ptr;
- const auto struct_var = namer_.Variable(struct_def.name);
+ const auto struct_var = namer_.Variable(struct_def);
GenReceiverForObjectAPI(struct_def, code_ptr);
code_base += "_UnPack(self, " + struct_var + "):";
@@ -1269,7 +1273,7 @@
void GenPackForStruct(const StructDef &struct_def,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto struct_fn = namer_.Function(struct_def.name);
+ const auto struct_fn = namer_.Function(struct_def);
GenReceiverForObjectAPI(struct_def, code_ptr);
code += "Pack(self, builder):";
@@ -1289,9 +1293,9 @@
std::string *code_ptr) const {
auto &code_prefix = *code_prefix_ptr;
auto &code = *code_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto struct_type = namer_.Type(struct_def.name);
- const auto field_method = namer_.Method(field.name);
+ const auto field_field = namer_.Field(field);
+ const auto struct_type = namer_.Type(struct_def);
+ const auto field_method = namer_.Method(field);
// Creates the field.
code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
@@ -1332,9 +1336,9 @@
std::string *code_ptr,
int indents) const {
auto &code = *code_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
- const auto struct_type = namer_.Type(struct_def.name);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_type = namer_.Type(struct_def);
const auto vectortype = field.value.type.VectorType();
code += GenIndents(indents) + struct_type + "Start" + field_method +
@@ -1368,9 +1372,9 @@
std::string *code_ptr) const {
auto &code = *code_ptr;
auto &code_prefix = *code_prefix_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
- const auto struct_type = namer_.Type(struct_def.name);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_type = namer_.Type(struct_def);
// Adds the field into the struct.
code += GenIndents(2) + "if self." + field_field + " is not None:";
@@ -1411,9 +1415,9 @@
std::string *code_ptr) const {
auto &code_prefix = *code_prefix_ptr;
auto &code = *code_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
- const auto struct_type = namer_.Type(struct_def.name);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_type = namer_.Type(struct_def);
if (field.value.type.struct_def->fixed) {
// Pure struct fields need to be created along with their parent
@@ -1438,9 +1442,9 @@
std::string *code_ptr) const {
auto &code_prefix = *code_prefix_ptr;
auto &code = *code_ptr;
- const auto field_field = namer_.Field(field.name);
- const auto field_method = namer_.Method(field.name);
- const auto struct_type = namer_.Type(struct_def.name);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_type = namer_.Type(struct_def);
// TODO(luwa): TypeT should be moved under the None check as well.
code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
@@ -1455,8 +1459,8 @@
std::string *code_ptr) const {
auto &code_base = *code_ptr;
std::string code, code_prefix;
- const auto struct_var = namer_.Variable(struct_def.name);
- const auto struct_type = namer_.Type(struct_def.name);
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto struct_type = namer_.Type(struct_def);
GenReceiverForObjectAPI(struct_def, code_ptr);
code_base += "Pack(self, builder):";
@@ -1466,8 +1470,8 @@
auto &field = **it;
if (field.deprecated) continue;
- const auto field_method = namer_.Method(field.name);
- const auto field_field = namer_.Field(field.name);
+ const auto field_method = namer_.Method(field);
+ const auto field_field = namer_.Field(field);
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
@@ -1555,12 +1559,12 @@
void GenUnionCreatorForStruct(const EnumDef &enum_def, const EnumVal &ev,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto union_type = namer_.Type(enum_def.name);
- const auto variant = namer_.Variant(ev.name);
- auto field_type = namer_.ObjectType(GenTypeGet(ev.union_type));
+ const auto union_type = namer_.Type(enum_def);
+ const auto variant = namer_.Variant(ev);
+ auto field_type = namer_.ObjectType(*ev.union_type.struct_def);
- code += GenIndents(1) + "if unionType == " + union_type + "()." +
- variant + ":";
+ code +=
+ GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":";
if (parser_.opts.include_dependence_headers) {
auto package_reference = GenPackageReference(ev.union_type);
code += GenIndents(2) + "import " + package_reference;
@@ -1573,11 +1577,11 @@
void GenUnionCreatorForString(const EnumDef &enum_def, const EnumVal &ev,
std::string *code_ptr) const {
auto &code = *code_ptr;
- const auto union_type = namer_.Type(enum_def.name);
- const auto variant = namer_.Variant(ev.name);
+ const auto union_type = namer_.Type(enum_def);
+ const auto variant = namer_.Variant(ev);
- code += GenIndents(1) + "if unionType == " + union_type + "()." +
- variant + ":";
+ code +=
+ GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":";
code += GenIndents(2) + "tab = Table(table.Bytes, table.Pos)";
code += GenIndents(2) + "union = tab.String(table.Pos)";
code += GenIndents(2) + "return union";
@@ -1588,7 +1592,7 @@
if (enum_def.generated) return;
auto &code = *code_ptr;
- const auto enum_fn = namer_.Function(enum_def.name);
+ const auto enum_fn = namer_.Function(enum_def);
code += "\n";
code += "def " + enum_fn + "Creator(unionType, table):";
@@ -1721,7 +1725,7 @@
if (parser_.opts.one_file && !enumcode.empty()) {
*one_file_code += enumcode + "\n\n";
} else {
- if (!SaveType(namer_.File(enum_def.name, SkipFile::Suffix),
+ if (!SaveType(namer_.File(enum_def, SkipFile::Suffix),
*enum_def.defined_namespace, enumcode, false))
return false;
}
@@ -1742,7 +1746,7 @@
if (parser_.opts.one_file && !declcode.empty()) {
*one_file_code += declcode + "\n\n";
} else {
- if (!SaveType(namer_.File(struct_def.name, SkipFile::Suffix),
+ if (!SaveType(namer_.File(struct_def, SkipFile::Suffix),
*struct_def.defined_namespace, declcode, true))
return false;
}
@@ -1789,7 +1793,7 @@
private:
const SimpleFloatConstantGenerator float_const_gen_;
- const Namer namer_;
+ const IdlNamer namer_;
};
} // namespace python
diff --git a/third_party/flatbuffers/src/idl_gen_rust.cpp b/third_party/flatbuffers/src/idl_gen_rust.cpp
index 0b0ad9a..64391d0 100644
--- a/third_party/flatbuffers/src/idl_gen_rust.cpp
+++ b/third_party/flatbuffers/src/idl_gen_rust.cpp
@@ -20,11 +20,12 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
-#include "namer.h"
+#include "idl_namer.h"
namespace flatbuffers {
+namespace {
-Namer::Config RustDefaultConfig() {
+static Namer::Config RustDefaultConfig() {
// Historical note: We've been using "keep" casing since the original
// implementation, presumably because Flatbuffers schema style and Rust style
// roughly align. We are not going to enforce proper casing since its an
@@ -37,6 +38,7 @@
/*variables=*/Case::kUnknown, // Unused.
/*variants=*/Case::kKeep,
/*enum_variant_seperator=*/"::",
+ /*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
/*namespaces=*/Case::kSnake,
/*namespace_seperator=*/"::",
/*object_prefix=*/"",
@@ -50,7 +52,7 @@
/*filename_extension=*/".rs" };
}
-std::set<std::string> RustKeywords() {
+static std::set<std::string> RustKeywords() {
return {
// https://doc.rust-lang.org/book/second-edition/appendix-01-keywords.html
"as",
@@ -172,7 +174,7 @@
};
// Convert a Type to a FullType (exhaustive).
-FullType GetFullType(const Type &type) {
+static FullType GetFullType(const Type &type) {
// N.B. The order of these conditionals matters for some types.
if (IsString(type)) {
@@ -262,15 +264,16 @@
return ftBool;
}
-bool IsBitFlagsEnum(const EnumDef &enum_def) {
+static bool IsBitFlagsEnum(const EnumDef &enum_def) {
return enum_def.attributes.Lookup("bit_flags") != nullptr;
}
// TableArgs make required non-scalars "Option<_>".
// TODO(cneo): Rework how we do defaults and stuff.
-bool IsOptionalToBuilder(const FieldDef &field) {
+static bool IsOptionalToBuilder(const FieldDef &field) {
return field.IsOptional() || !IsScalar(field.value.type.base_type);
}
+} // namespace
bool GenerateRustModuleRootFile(const Parser &parser,
const std::string &output_dir) {
@@ -279,7 +282,7 @@
// so return true.
return true;
}
- Namer namer(RustDefaultConfig().WithFlagOptions(parser.opts, output_dir),
+ Namer namer(WithFlagOptions(RustDefaultConfig(), parser.opts, output_dir),
RustKeywords());
// We gather the symbols into a tree of namespaces (which are rust mods) and
// generate a file that gathers them all.
@@ -329,6 +332,7 @@
code +=
"// Automatically generated by the Flatbuffers compiler. "
"Do not modify.";
+ code += "// @generated";
root_module.GenerateImports(code);
const bool success =
SaveFile((output_dir + "mod.rs").c_str(), code.ToString(), false);
@@ -344,8 +348,8 @@
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "::", "rs"),
cur_name_space_(nullptr),
- namer_({ RustDefaultConfig().WithFlagOptions(parser.opts, path),
- RustKeywords() }) {
+ namer_(WithFlagOptions(RustDefaultConfig(), parser.opts, path),
+ RustKeywords()) {
// TODO: Namer flag overrides should be in flatc or flatc_main.
code_.SetPadding(" ");
}
@@ -367,9 +371,14 @@
code_.Clear();
code_ += "// " + std::string(FlatBuffersGeneratedWarning());
code_ += "#![allow(unused_imports)]";
+ code_ += "// @generated";
+ code_ += "extern crate alloc;";
code_ += "extern crate flatbuffers;";
- code_ += "use std::mem;";
- code_ += "use std::cmp::Ordering;";
+ code_ += "use alloc::boxed::Box;";
+ code_ += "use alloc::string::{String, ToString};";
+ code_ += "use alloc::vec::Vec;";
+ code_ += "use core::mem;";
+ code_ += "use core::cmp::Ordering;";
if (parser_.opts.rust_serialize) {
code_ += "extern crate serde;";
code_ +=
@@ -381,9 +390,9 @@
gen_symbol(symbol);
const std::string directories =
- namer_.Directories(symbol.defined_namespace->components);
+ namer_.Directories(*symbol.defined_namespace);
EnsureDirExists(directories);
- const std::string file_path = directories + namer_.File(symbol.name);
+ const std::string file_path = directories + namer_.File(symbol);
const bool save_success =
SaveFile(file_path.c_str(), code_.ToString(), /*binary=*/false);
if (!save_success) return false;
@@ -419,6 +428,7 @@
bool GenerateOneFile() {
code_.Clear();
code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+ code_ += "// @generated";
assert(!cur_name_space_);
@@ -527,8 +537,11 @@
return false;
}
- std::string NamespacedNativeName(const Definition &def) {
- return WrapInNameSpace(def.defined_namespace, namer_.ObjectType(def.name));
+ std::string NamespacedNativeName(const EnumDef &def) {
+ return WrapInNameSpace(def.defined_namespace, namer_.ObjectType(def));
+ }
+ std::string NamespacedNativeName(const StructDef &def) {
+ return WrapInNameSpace(def.defined_namespace, namer_.ObjectType(def));
}
std::string WrapInNameSpace(const Definition &def) const {
@@ -664,7 +677,7 @@
std::string GetEnumValue(const EnumDef &enum_def,
const EnumVal &enum_val) const {
- return namer_.EnumVariant(enum_def.name, enum_val.name);
+ return namer_.EnumVariant(enum_def, enum_val);
}
// 1 suffix since old C++ can't figure out the overload.
@@ -672,7 +685,7 @@
std::function<void(const EnumVal &)> cb) {
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
const auto &ev = **it;
- code_.SetValue("VARIANT", namer_.Variant(ev.name));
+ code_.SetValue("VARIANT", namer_.Variant(ev));
code_.SetValue("VALUE", enum_def.ToString(ev));
code_.IncrementIdentLevel();
cb(ev);
@@ -691,7 +704,10 @@
// an enum match function,
// and an enum array of values
void GenEnum(const EnumDef &enum_def) {
- code_.SetValue("ENUM_TY", namer_.Type(enum_def.name));
+ const bool is_private = parser_.opts.no_leak_private_annotations &&
+ (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));
code_.SetValue("ENUM_NAMESPACE", namer_.Namespace(enum_def.name));
code_.SetValue("ENUM_CONSTANT", namer_.Constant(enum_def.name));
@@ -711,7 +727,7 @@
code_ += " flatbuffers::bitflags::bitflags! {";
GenComment(enum_def.doc_comment, " ");
code_ += " #[derive(Default)]";
- code_ += " pub struct {{ENUM_TY}}: {{BASE_TYPE}} {";
+ code_ += " {{ACCESS_TYPE}} struct {{ENUM_TY}}: {{BASE_TYPE}} {";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
this->GenComment(ev.doc_comment, " ");
code_ += " const {{VARIANT}} = {{VALUE}};";
@@ -744,7 +760,7 @@
code_ += "pub const ENUM_VALUES_{{ENUM_CONSTANT}}: [{{ENUM_TY}}; " +
num_fields + "] = [";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
- code_ += namer_.EnumVariant(enum_def.name, ev.name) + ",";
+ code_ += namer_.EnumVariant(enum_def, ev) + ",";
});
code_ += "];";
code_ += "";
@@ -757,7 +773,7 @@
"#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, "
"Default)]";
code_ += "#[repr(transparent)]";
- code_ += "pub struct {{ENUM_TY}}(pub {{BASE_TYPE}});";
+ code_ += "{{ACCESS_TYPE}} struct {{ENUM_TY}}(pub {{BASE_TYPE}});";
code_ += "#[allow(non_upper_case_globals)]";
code_ += "impl {{ENUM_TY}} {";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
@@ -783,10 +799,10 @@
code_ += "}";
// Generate Debug. Unknown variants are printed like "<UNKNOWN 42>".
- code_ += "impl std::fmt::Debug for {{ENUM_TY}} {";
+ code_ += "impl core::fmt::Debug for {{ENUM_TY}} {";
code_ +=
- " fn fmt(&self, f: &mut std::fmt::Formatter) ->"
- " std::fmt::Result {";
+ " fn fmt(&self, f: &mut core::fmt::Formatter) ->"
+ " core::fmt::Result {";
code_ += " if let Some(name) = self.variant_name() {";
code_ += " f.write_str(name)";
code_ += " } else {";
@@ -873,8 +889,8 @@
if (enum_def.is_union) {
// Generate typesafe offset(s) for unions
- code_.SetValue("UNION_TYPE", namer_.Type(enum_def.name));
- code_ += "pub struct {{UNION_TYPE}}UnionTableOffset {}";
+ code_.SetValue("UNION_TYPE", namer_.Type(enum_def));
+ code_ += "{{ACCESS_TYPE}} struct {{UNION_TYPE}}UnionTableOffset {}";
code_ += "";
if (parser_.opts.generate_object_based_api) { GenUnionObject(enum_def); }
}
@@ -886,13 +902,12 @@
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &enum_val = **it;
if (enum_val.union_type.base_type == BASE_TYPE_NONE) continue;
- code_.SetValue("VARIANT_NAME", namer_.Variant(enum_val.name));
+ code_.SetValue("VARIANT_NAME", namer_.Variant(enum_val));
// For legacy reasons, enum variants are Keep case while enum native
// variants are UpperCamel case.
- code_.SetValue(
- "NATIVE_VARIANT",
- ConvertCase(namer_.EscapeKeyword(enum_val.name), Case::kUpperCamel));
- code_.SetValue("U_ELEMENT_NAME", namer_.Method(enum_val.name));
+ code_.SetValue("NATIVE_VARIANT",
+ namer_.LegacyRustNativeVariant(enum_val));
+ code_.SetValue("U_ELEMENT_NAME", namer_.Method(enum_val));
code_.SetValue("U_ELEMENT_TABLE_TYPE",
NamespacedNativeName(*enum_val.union_type.struct_def));
code_.IncrementIdentLevel();
@@ -901,16 +916,16 @@
}
}
void GenUnionObject(const EnumDef &enum_def) {
- code_.SetValue("ENUM_TY", namer_.Type(enum_def.name));
- code_.SetValue("ENUM_FN", namer_.Function(enum_def.name));
- code_.SetValue("ENUM_OTY", namer_.ObjectType(enum_def.name));
+ code_.SetValue("ENUM_TY", namer_.Type(enum_def));
+ code_.SetValue("ENUM_FN", namer_.Function(enum_def));
+ code_.SetValue("ENUM_OTY", namer_.ObjectType(enum_def));
// Generate native union.
code_ += "#[allow(clippy::upper_case_acronyms)]"; // NONE's spelling is
// intended.
code_ += "#[non_exhaustive]";
code_ += "#[derive(Debug, Clone, PartialEq)]";
- code_ += "pub enum {{ENUM_OTY}} {";
+ code_ += "{{ACCESS_TYPE}} enum {{ENUM_OTY}} {";
code_ += " NONE,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
code_ += "{{NATIVE_VARIANT}}(Box<{{U_ELEMENT_TABLE_TYPE}}>),";
@@ -962,7 +977,7 @@
"pub fn take_{{U_ELEMENT_NAME}}(&mut self) -> "
"Option<Box<{{U_ELEMENT_TABLE_TYPE}}>> {";
code_ += " if let Self::{{NATIVE_VARIANT}}(_) = self {";
- code_ += " let v = std::mem::replace(self, Self::NONE);";
+ code_ += " let v = core::mem::replace(self, Self::NONE);";
code_ += " if let Self::{{NATIVE_VARIANT}}(w) = v {";
code_ += " Some(w)";
code_ += " } else {";
@@ -998,13 +1013,6 @@
code_ += "}"; // End union methods impl.
}
- std::string GetFieldOffsetName(const FieldDef &field) {
- // FIXME: VT_FIELD_NAME is not screaming snake case by legacy mistake.
- // but changing this is probably a breaking change.
- return "VT_" +
- ConvertCase(namer_.EscapeKeyword(field.name), Case::kAllUpper);
- }
-
enum DefaultContext { kBuilder, kAccessor, kObject };
std::string GetDefaultValue(const FieldDef &field,
const DefaultContext context) {
@@ -1034,7 +1042,7 @@
if (!ev) return "Default::default()"; // Bitflags enum.
return WrapInNameSpace(
field.value.type.enum_def->defined_namespace,
- namer_.EnumVariant(field.value.type.enum_def->name, ev->name));
+ namer_.EnumVariant(*field.value.type.enum_def, *ev));
}
case ftUnionValue: {
return ObjectFieldType(field, true) + "::NONE";
@@ -1540,7 +1548,7 @@
std::string GenTableAccessorFuncBody(const FieldDef &field,
const std::string &lifetime) {
- const std::string vt_offset = GetFieldOffsetName(field);
+ const std::string vt_offset = namer_.LegacyRustFieldOffsetName(field);
const std::string typname = FollowType(field.value.type, lifetime);
// Default-y fields (scalars so far) are neither optional nor required.
const std::string default_value =
@@ -1587,9 +1595,9 @@
const EnumVal &ev = **it;
// TODO(cneo): Can variants be deprecated, should we skip them?
if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
- code_.SetValue("U_ELEMENT_ENUM_TYPE",
- WrapInNameSpace(def.defined_namespace,
- namer_.EnumVariant(def.name, ev.name)));
+ code_.SetValue(
+ "U_ELEMENT_ENUM_TYPE",
+ WrapInNameSpace(def.defined_namespace, namer_.EnumVariant(def, ev)));
code_.SetValue(
"U_ELEMENT_TABLE_TYPE",
WrapInNameSpace(ev.union_type.struct_def->defined_namespace,
@@ -1606,11 +1614,11 @@
// diff when refactoring to the `ForAllX` helper functions.
auto go = [&](const FieldDef &field) {
if (field.deprecated) return;
- code_.SetValue("OFFSET_NAME", GetFieldOffsetName(field));
+ code_.SetValue("OFFSET_NAME", namer_.LegacyRustFieldOffsetName(field));
code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
- code_.SetValue("FIELD", namer_.Field(field.name));
+ code_.SetValue("FIELD", namer_.Field(field));
code_.SetValue("BLDR_DEF_VAL", GetDefaultValue(field, kBuilder));
- code_.SetValue("DISCRIMINANT", namer_.Method(field.name) + "_type");
+ code_.SetValue("DISCRIMINANT", namer_.Field(field) + "_type");
code_.IncrementIdentLevel();
cb(field);
code_.DecrementIdentLevel();
@@ -1625,18 +1633,22 @@
// Generate an accessor struct, builder struct, and create function for a
// table.
void GenTable(const StructDef &struct_def) {
- code_.SetValue("STRUCT_TY", namer_.Type(struct_def.name));
- code_.SetValue("STRUCT_FN", namer_.Function(struct_def.name));
+
+ 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));
+ code_.SetValue("STRUCT_FN", namer_.Function(struct_def));
// Generate an offset type, the base type, the Follow impl, and the
// init_from_table impl.
- code_ += "pub enum {{STRUCT_TY}}Offset {}";
+ code_ += "{{ACCESS_TYPE}} enum {{STRUCT_TY}}Offset {}";
code_ += "#[derive(Copy, Clone, PartialEq)]";
code_ += "";
GenComment(struct_def.doc_comment);
- code_ += "pub struct {{STRUCT_TY}}<'a> {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}<'a> {";
code_ += " pub _tab: flatbuffers::Table<'a>,";
code_ += "}";
code_ += "";
@@ -1707,7 +1719,7 @@
if (parser_.opts.generate_object_based_api) {
// TODO(cneo): Replace more for loops with ForAllX stuff.
// TODO(cneo): Manage indentation with IncrementIdentLevel?
- code_.SetValue("STRUCT_OTY", namer_.ObjectType(struct_def.name));
+ code_.SetValue("STRUCT_OTY", namer_.ObjectType(struct_def));
code_ += " pub fn unpack(&self) -> {{STRUCT_OTY}} {";
ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
const Type &type = field.value.type;
@@ -1948,7 +1960,7 @@
const EnumDef &union_def = *field.value.type.enum_def;
code_.SetValue("UNION_TYPE", WrapInNameSpace(union_def));
code_.SetValue("UNION_TYPE_OFFSET_NAME",
- GetFieldOffsetName(field) + "_TYPE");
+ namer_.LegacyRustFieldOffsetName(field) + "_TYPE");
code_ +=
"\n .visit_union::<{{UNION_TYPE}}, _>("
"\"{{FIELD}}_type\", Self::{{UNION_TYPE_OFFSET_NAME}}, "
@@ -1974,7 +1986,7 @@
// Generate an args struct:
code_.SetValue("MAYBE_LT",
TableBuilderArgsNeedsLifetime(struct_def) ? "<'a>" : "");
- code_ += "pub struct {{STRUCT_TY}}Args{{MAYBE_LT}} {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}Args{{MAYBE_LT}} {";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
code_.SetValue("PARAM_TYPE", TableBuilderArgsDefnType(field, "'a"));
code_ += " pub {{FIELD}}: {{PARAM_TYPE}},";
@@ -2019,12 +2031,12 @@
if (type.base_type == BASE_TYPE_UNION) {
const auto &enum_def = *type.enum_def;
code_.SetValue("ENUM_TY", WrapInNameSpace(enum_def));
- code_.SetValue("FIELD", namer_.Field(field.name));
+ code_.SetValue("FIELD", namer_.Field(field));
code_ += " match self.{{FIELD}}_type() {";
code_ += " {{ENUM_TY}}::NONE => (),";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
- code_.SetValue("FIELD", namer_.Field(field.name));
+ code_.SetValue("FIELD", namer_.Field(field));
code_ += " {{ENUM_TY}}::{{VARIANT_NAME}} => {";
code_ +=
" let f = "
@@ -2063,7 +2075,7 @@
}
// Generate a builder struct:
- code_ += "pub struct {{STRUCT_TY}}Builder<'a: 'b, 'b> {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}Builder<'a: 'b, 'b> {";
code_ += " fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,";
code_ +=
" start_: flatbuffers::WIPOffset<"
@@ -2074,7 +2086,7 @@
code_ += "impl<'a: 'b, 'b> {{STRUCT_TY}}Builder<'a, 'b> {";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
const bool is_scalar = IsScalar(field.value.type.base_type);
- std::string offset = GetFieldOffsetName(field);
+ std::string offset = namer_.LegacyRustFieldOffsetName(field);
// Generate functions to add data, which take one of two forms.
//
// If a value has a default:
@@ -2086,8 +2098,7 @@
// fn add_x(x_: type) {
// fbb_.push_slot_always::<type>(offset, x_);
// }
- code_.SetValue("FIELD_OFFSET",
- namer_.Type(struct_def.name) + "::" + offset);
+ code_.SetValue("FIELD_OFFSET", namer_.Type(struct_def) + "::" + offset);
code_.SetValue("FIELD_TYPE", TableBuilderArgsAddFuncType(field, "'b "));
code_.SetValue("FUNC_BODY", TableBuilderArgsAddFuncBody(field));
code_ += "#[inline]";
@@ -2135,10 +2146,10 @@
code_ += "}";
code_ += "";
- code_ += "impl std::fmt::Debug for {{STRUCT_TY}}<'_> {";
+ code_ += "impl core::fmt::Debug for {{STRUCT_TY}}<'_> {";
code_ +=
- " fn fmt(&self, f: &mut std::fmt::Formatter<'_>"
- ") -> std::fmt::Result {";
+ " fn fmt(&self, f: &mut core::fmt::Formatter<'_>"
+ ") -> core::fmt::Result {";
code_ += " let mut ds = f.debug_struct(\"{{STRUCT_TY}}\");";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
if (GetFullType(field.value.type) == ftUnionValue) {
@@ -2179,13 +2190,13 @@
}
void GenTableObject(const StructDef &table) {
- code_.SetValue("STRUCT_OTY", namer_.ObjectType(table.name));
- code_.SetValue("STRUCT_TY", namer_.Type(table.name));
+ code_.SetValue("STRUCT_OTY", namer_.ObjectType(table));
+ code_.SetValue("STRUCT_TY", namer_.Type(table));
// Generate the native object.
code_ += "#[non_exhaustive]";
code_ += "#[derive(Debug, Clone, PartialEq)]";
- code_ += "pub struct {{STRUCT_OTY}} {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_OTY}} {";
ForAllObjectTableFields(table, [&](const FieldDef &field) {
// Union objects combine both the union discriminant and value, so we
// skip making a field for the discriminant.
@@ -2230,7 +2241,7 @@
case ftUnionKey: return; // Generate union type with union value.
case ftUnionValue: {
code_.SetValue("ENUM_METHOD",
- namer_.Method(field.value.type.enum_def->name));
+ namer_.Method(*field.value.type.enum_def));
code_ +=
" let {{FIELD}}_type = "
"self.{{FIELD}}.{{ENUM_METHOD}}_type();";
@@ -2318,7 +2329,7 @@
for (auto it = v.begin(); it != v.end(); it++) {
const FieldDef &field = **it;
if (field.deprecated) continue;
- code_.SetValue("FIELD", namer_.Field(field.name));
+ code_.SetValue("FIELD", namer_.Field(field));
code_.SetValue("FIELD_OTY", ObjectFieldType(field, true));
code_.IncrementIdentLevel();
cb(field);
@@ -2358,7 +2369,7 @@
code_ += "#[inline]";
code_ +=
"pub fn key_compare_with_value(&self, val: {{KEY_TYPE}}) -> "
- "::std::cmp::Ordering {";
+ "::core::cmp::Ordering {";
code_ += " let key = self.{{FIELD}}();";
code_ += " key.cmp({{REF}}val)";
code_ += "}";
@@ -2368,8 +2379,8 @@
// must only be called if the root table is defined.
void GenRootTableFuncs(const StructDef &struct_def) {
FLATBUFFERS_ASSERT(parser_.root_struct_def_ && "root table not defined");
- code_.SetValue("STRUCT_TY", namer_.Type(struct_def.name));
- code_.SetValue("STRUCT_FN", namer_.Function(struct_def.name));
+ code_.SetValue("STRUCT_TY", namer_.Type(struct_def));
+ code_.SetValue("STRUCT_FN", namer_.Function(struct_def));
code_.SetValue("STRUCT_CONST", namer_.Constant(struct_def.name));
// The root datatype accessors:
@@ -2579,7 +2590,7 @@
const auto &field = **it;
code_.SetValue("FIELD_TYPE", GetTypeGet(field.value.type));
code_.SetValue("FIELD_OTY", ObjectFieldType(field, false));
- code_.SetValue("FIELD", namer_.Field(field.name));
+ code_.SetValue("FIELD", namer_.Field(field));
code_.SetValue("FIELD_OFFSET", NumToString(offset_to_field));
code_.SetValue(
"REF",
@@ -2593,12 +2604,15 @@
}
// 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 &&
+ (struct_def.attributes.Lookup("private") != nullptr);
+ code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
// Generates manual padding and alignment.
// Variables are private because they contain little endian data on all
// platforms.
GenComment(struct_def.doc_comment);
code_.SetValue("ALIGN", NumToString(struct_def.minalign));
- code_.SetValue("STRUCT_TY", namer_.Type(struct_def.name));
+ code_.SetValue("STRUCT_TY", namer_.Type(struct_def));
code_.SetValue("STRUCT_SIZE", NumToString(struct_def.bytesize));
// We represent Flatbuffers-structs in Rust-u8-arrays since the data may be
@@ -2610,7 +2624,7 @@
code_ += "// struct {{STRUCT_TY}}, aligned to {{ALIGN}}";
code_ += "#[repr(transparent)]";
code_ += "#[derive(Clone, Copy, PartialEq)]";
- code_ += "pub struct {{STRUCT_TY}}(pub [u8; {{STRUCT_SIZE}}]);";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}(pub [u8; {{STRUCT_SIZE}}]);";
code_ += "impl Default for {{STRUCT_TY}} { ";
code_ += " fn default() -> Self { ";
code_ += " Self([0; {{STRUCT_SIZE}}])";
@@ -2618,10 +2632,10 @@
code_ += "}";
// Debug for structs.
- code_ += "impl std::fmt::Debug for {{STRUCT_TY}} {";
+ code_ += "impl core::fmt::Debug for {{STRUCT_TY}} {";
code_ +=
- " fn fmt(&self, f: &mut std::fmt::Formatter"
- ") -> std::fmt::Result {";
+ " fn fmt(&self, f: &mut core::fmt::Formatter"
+ ") -> core::fmt::Result {";
code_ += " f.debug_struct(\"{{STRUCT_TY}}\")";
ForAllStructFields(struct_def, [&](const FieldDef &unused) {
(void)unused;
@@ -2657,7 +2671,7 @@
code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
code_ += " let src = unsafe {";
code_ +=
- " ::std::slice::from_raw_parts("
+ " ::core::slice::from_raw_parts("
"self as *const {{STRUCT_TY}} as *const u8, Self::size())";
code_ += " };";
code_ += " dst.copy_from_slice(src);";
@@ -2670,7 +2684,7 @@
code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
code_ += " let src = unsafe {";
code_ +=
- " ::std::slice::from_raw_parts("
+ " ::core::slice::from_raw_parts("
"*self as *const {{STRUCT_TY}} as *const u8, Self::size())";
code_ += " };";
code_ += " dst.copy_from_slice(src);";
@@ -2798,7 +2812,7 @@
NumToString(InlineSize(field.value.type)));
code_ += "pub fn set_{{FIELD}}(&mut self, x: &{{FIELD_TYPE}}) {";
code_ += " unsafe {";
- code_ += " std::ptr::copy(";
+ code_ += " core::ptr::copy(";
code_ += " x.as_ptr() as *const u8,";
code_ += " self.0.as_mut_ptr().add({{FIELD_OFFSET}}),";
code_ += " {{FIELD_SIZE}},";
@@ -2824,7 +2838,7 @@
// Generate Object API unpack method.
if (parser_.opts.generate_object_based_api) {
- code_.SetValue("STRUCT_OTY", namer_.ObjectType(struct_def.name));
+ code_.SetValue("STRUCT_OTY", namer_.ObjectType(struct_def));
code_ += " pub fn unpack(&self) -> {{STRUCT_OTY}} {";
code_ += " {{STRUCT_OTY}} {";
ForAllStructFields(struct_def, [&](const FieldDef &field) {
@@ -2857,7 +2871,7 @@
if (parser_.opts.generate_object_based_api) {
// Struct declaration
code_ += "#[derive(Debug, Clone, PartialEq, Default)]";
- code_ += "pub struct {{STRUCT_OTY}} {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_OTY}} {";
ForAllStructFields(struct_def, [&](const FieldDef &field) {
(void)field; // unused.
code_ += "pub {{FIELD}}: {{FIELD_OTY}},";
@@ -2915,8 +2929,8 @@
}
}
}
- code_ += indent + "use std::mem;";
- code_ += indent + "use std::cmp::Ordering;";
+ code_ += indent + "use core::mem;";
+ code_ += indent + "use core::cmp::Ordering;";
code_ += "";
if (parser_.opts.rust_serialize) {
code_ += indent + "extern crate serde;";
@@ -2973,7 +2987,7 @@
}
private:
- Namer namer_;
+ IdlNamer namer_;
};
} // namespace rust
diff --git a/third_party/flatbuffers/src/idl_gen_swift.cpp b/third_party/flatbuffers/src/idl_gen_swift.cpp
index c3c322f..b3baa28 100644
--- a/third_party/flatbuffers/src/idl_gen_swift.cpp
+++ b/third_party/flatbuffers/src/idl_gen_swift.cpp
@@ -21,21 +21,133 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
namespace swift {
-inline std::string GenIndirect(const std::string &reading) {
+namespace {
+
+static Namer::Config SwiftDefaultConfig() {
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kLowerCamel,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kLowerCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kLowerCamel,
+ /*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"_",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".swift" };
+}
+
+static std::set<std::string> SwiftKeywords() {
+ return {
+ "associatedtype",
+ "class",
+ "deinit",
+ "enum",
+ "extension",
+ "fileprivate",
+ "func",
+ "import",
+ "init",
+ "inout",
+ "internal",
+ "let",
+ "open",
+ "operator",
+ "private",
+ "protocol",
+ "public",
+ "rethrows",
+ "static",
+ "struct",
+ "subscript",
+ "typealias",
+ "var",
+ "break",
+ "case",
+ "continue",
+ "default",
+ "defer",
+ "do",
+ "else",
+ "fallthrough",
+ "for",
+ "guard",
+ "if",
+ "in",
+ "repeat",
+ "return",
+ "switch",
+ "where",
+ "while",
+ "Any",
+ "catch",
+ "false",
+ "is",
+ "nil",
+ "super",
+ "self",
+ "Self",
+ "throw",
+ "throws",
+ "true",
+ "try",
+ "associativity",
+ "convenience",
+ "dynamic",
+ "didSet",
+ "final",
+ "get",
+ "infix",
+ "indirect",
+ "lazy",
+ "left",
+ "mutating",
+ "none",
+ "nonmutating",
+ "optional",
+ "override",
+ "postfix",
+ "precedence",
+ "prefix",
+ "Protocol",
+ "required",
+ "right",
+ "set",
+ "Type",
+ "unowned",
+ "weak",
+ "willSet",
+ "Void",
+ };
+}
+
+static std::string GenIndirect(const std::string &reading) {
return "{{ACCESS}}.indirect(" + reading + ")";
}
-inline std::string GenArrayMainBody(const std::string &optional) {
- return "{{ACCESS_TYPE}} func {{VALUENAME}}(at index: Int32) -> "
+static std::string GenArrayMainBody(const std::string &optional) {
+ return "{{ACCESS_TYPE}} func {{FIELDMETHOD}}(at index: Int32) -> "
"{{VALUETYPE}}" +
optional + " { ";
}
+} // namespace
+
class SwiftGenerator : public BaseGenerator {
private:
CodeWriter code_;
@@ -45,92 +157,11 @@
public:
SwiftGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
- : BaseGenerator(parser, path, file_name, "", "_", "swift") {
+ : BaseGenerator(parser, path, file_name, "", "_", "swift"),
+ namer_(WithFlagOptions(SwiftDefaultConfig(), parser.opts, path),
+ SwiftKeywords()) {
namespace_depth = 0;
code_.SetPadding(" ");
- static const char *const keywords[] = {
- "associatedtype",
- "class",
- "deinit",
- "enum",
- "extension",
- "fileprivate",
- "func",
- "import",
- "init",
- "inout",
- "internal",
- "let",
- "open",
- "operator",
- "private",
- "protocol",
- "public",
- "rethrows",
- "static",
- "struct",
- "subscript",
- "typealias",
- "var",
- "break",
- "case",
- "continue",
- "default",
- "defer",
- "do",
- "else",
- "fallthrough",
- "for",
- "guard",
- "if",
- "in",
- "repeat",
- "return",
- "switch",
- "where",
- "while",
- "Any",
- "catch",
- "false",
- "is",
- "nil",
- "super",
- "self",
- "Self",
- "throw",
- "throws",
- "true",
- "try",
- "associativity",
- "convenience",
- "dynamic",
- "didSet",
- "final",
- "get",
- "infix",
- "indirect",
- "lazy",
- "left",
- "mutating",
- "none",
- "nonmutating",
- "optional",
- "override",
- "postfix",
- "precedence",
- "prefix",
- "Protocol",
- "required",
- "right",
- "set",
- "Type",
- "unowned",
- "weak",
- "willSet",
- "Void",
- nullptr,
- };
- for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
}
bool generate() {
@@ -140,9 +171,14 @@
code_ += "// " + std::string(FlatBuffersGeneratedWarning());
code_ += "// swiftlint:disable all";
code_ += "// swiftformat:disable all\n";
- code_ += "import FlatBuffers\n";
- // Generate code for all the enum declarations.
+ if (parser_.opts.include_dependence_headers || parser_.opts.generate_all) {
+ if (parser_.opts.swift_implementation_only)
+ code_ += "@_implementationOnly \\";
+ code_ += "import FlatBuffers\n";
+ }
+
+ // Generate code for all the enum declarations.
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
const auto &enum_def = **it;
@@ -183,10 +219,12 @@
// Generates the reader for swift
void GenStructReader(const StructDef &struct_def) {
- auto is_private_access = struct_def.attributes.Lookup("private");
+ const bool is_private_access =
+ parser_.opts.swift_implementation_only ||
+ struct_def.attributes.Lookup("private") != nullptr;
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
GenComment(struct_def.doc_comment);
- code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
+ code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
code_ +=
"{{ACCESS_TYPE}} struct {{STRUCTNAME}}: NativeStruct, Verifiable, "
"FlatbuffersInitializable\\";
@@ -203,14 +241,14 @@
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
if (!constructor.empty()) constructor += ", ";
- auto name = Name(field);
- auto type = GenType(field.value.type);
- code_.SetValue("VALUENAME", name);
+ const auto field_var = namer_.Variable(field);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", field_var);
if (IsEnum(field.value.type)) {
code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
}
@@ -218,18 +256,20 @@
GenComment(field.doc_comment);
std::string valueType =
IsEnum(field.value.type) ? "{{BASEVALUE}}" : "{{VALUETYPE}}";
- code_ += "private var _{{VALUENAME}}: " + valueType;
- auto accessing_value = IsEnum(field.value.type) ? ".value" : "";
- auto is_bool = IsBool(field.value.type.base_type);
- auto base_value = IsStruct(field.value.type) ? (type + "()")
- : is_bool ? ("0" == field.value.constant ? "false" : "true")
- : field.value.constant;
+ code_ += "private var _{{FIELDVAR}}: " + valueType;
+ const auto accessing_value = IsEnum(field.value.type) ? ".value" : "";
+ const auto is_bool = IsBool(field.value.type.base_type);
+ const auto base_value =
+ IsStruct(field.value.type) ? (type + "()")
+ : is_bool ? ("0" == field.value.constant ? "false" : "true")
+ : field.value.constant;
- main_constructor.push_back("_" + name + " = " + name + accessing_value);
- base_constructor.push_back("_" + name + " = " + base_value);
+ main_constructor.push_back("_" + field_var + " = " + field_var +
+ accessing_value);
+ base_constructor.push_back("_" + field_var + " = " + base_value);
if (field.padding) { GenPadding(field, &padding_id); }
- constructor += name + ": " + type;
+ constructor += field_var + ": " + type;
}
code_ += "";
BuildStructConstructor(struct_def);
@@ -241,23 +281,22 @@
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto name = Name(field);
- auto type = GenType(field.value.type);
- code_.SetValue("VALUENAME", name);
- code_.SetValue("VALUETYPE", type);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
+ code_.SetValue("VALUETYPE", GenType(field.value.type));
GenComment(field.doc_comment);
if (!IsEnum(field.value.type)) {
- code_ += GenReaderMainBody() + "_{{VALUENAME}} }";
+ code_ += GenReaderMainBody() + "_{{FIELDVAR}} }";
} else if (IsEnum(field.value.type)) {
code_ +=
- GenReaderMainBody() + "{{VALUETYPE}}(rawValue: _{{VALUENAME}})! }";
+ GenReaderMainBody() + "{{VALUETYPE}}(rawValue: _{{FIELDVAR}})! }";
}
}
code_ += "";
code_ +=
- "public static func verify<T>(_ verifier: inout Verifier, at position: "
+ "{{ACCESS_TYPE}} static func verify<T>(_ verifier: inout Verifier, at "
+ "position: "
"Int, of type: T.Type) throws where T: Verifiable {";
Indent();
code_ +=
@@ -275,22 +314,21 @@
code_ += "let {{ACCESS}} = Struct(bb: bb, position: o)";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto name = Name(field);
- auto type = field.value.type;
- code_.SetValue("VALUENAME", name);
+ const auto type = field.value.type;
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
code_.SetValue("VALUETYPE", GenType(type));
code_.SetValue("OFFSET", NumToString(field.value.offset));
if (IsScalar(type.base_type)) {
if (IsEnum(type))
code_.SetValue("VALUETYPE", GenTypeBasic(field.value.type, false));
code_ +=
- "_{{VALUENAME}} = {{ACCESS}}.readBuffer(of: {{VALUETYPE}}.self, "
+ "_{{FIELDVAR}} = {{ACCESS}}.readBuffer(of: {{VALUETYPE}}.self, "
"at: {{OFFSET}})";
} else {
code_ +=
- "_{{VALUENAME}} = {{VALUETYPE}}({{ACCESS}}.bb, o: "
+ "_{{FIELDVAR}} = {{VALUETYPE}}({{ACCESS}}.bb, o: "
"{{ACCESS}}.postion + {{OFFSET}})";
}
}
@@ -303,12 +341,11 @@
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto offset = NumToString(field.value.offset);
- auto name = Name(field);
- auto type = GenType(field.value.type);
- code_.SetValue("VALUENAME", name);
+ const auto offset = NumToString(field.value.offset);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
if (IsEnum(field.value.type)) {
code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
}
@@ -332,7 +369,7 @@
}
if (parser_.opts.generate_object_based_api) {
- GenerateObjectAPIExtensionHeader(NameWrappedInNameSpace(struct_def));
+ GenerateObjectAPIExtensionHeader(namer_.NamespacedType(struct_def));
code_ += "return builder.create(struct: obj)";
Outdent();
code_ += "}";
@@ -343,10 +380,12 @@
// Generates the create function for swift
void GenStructWriter(const StructDef &struct_def) {
- auto is_private_access = struct_def.attributes.Lookup("private");
+ const bool is_private_access =
+ parser_.opts.swift_implementation_only ||
+ struct_def.attributes.Lookup("private") != nullptr;
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
- code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
- code_.SetValue("SHORT_STRUCTNAME", Name(struct_def));
+ code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
+ code_.SetValue("SHORT_STRUCTNAME", namer_.Method(struct_def));
code_ += "extension {{STRUCTNAME}} {";
Indent();
code_ += "@discardableResult";
@@ -376,7 +415,7 @@
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
const auto &field_type = field.value.type;
if (IsStruct(field.value.type)) {
@@ -384,14 +423,15 @@
*field_type.struct_def, code_ptr, (nameprefix + field.name),
(object_name + "." + field.name), obj_api_named, is_obj_api);
} else {
- auto name = Name(field);
- auto type = GenType(field.value.type);
+ const auto field_var = namer_.Variable(field);
+ const auto field_field = namer_.Field(field);
+ const auto type = GenType(field.value.type);
if (!is_obj_api) {
- code += nameprefix + name + ": " + type;
+ code += nameprefix + field_var + ": " + type;
if (!IsEnum(field.value.type)) {
code += " = ";
- auto is_bool = IsBool(field.value.type.base_type);
- auto constant =
+ const auto is_bool = IsBool(field.value.type.base_type);
+ const auto constant =
is_bool ? ("0" == field.value.constant ? "false" : "true")
: field.value.constant;
code += constant;
@@ -399,8 +439,8 @@
code += ", ";
continue;
}
- code +=
- nameprefix + name + ": " + obj_api_named + object_name + "." + name;
+ code += nameprefix + field_var + ": " + obj_api_named + object_name +
+ "." + field_field;
code += ", ";
}
}
@@ -410,7 +450,9 @@
// Generates the reader for swift
void GenTable(const StructDef &struct_def) {
- auto is_private_access = struct_def.attributes.Lookup("private");
+ const bool is_private_access =
+ parser_.opts.swift_implementation_only ||
+ struct_def.attributes.Lookup("private") != nullptr;
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
GenObjectHeader(struct_def);
GenTableAccessors(struct_def);
@@ -435,7 +477,7 @@
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
if (field.deprecated) { continue; }
- code_.SetValue("OFFSET_NAME", Name(field));
+ code_.SetValue("OFFSET_NAME", namer_.Variable(field));
code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
code_ += "case {{OFFSET_NAME}} = {{OFFSET_VALUE}}";
}
@@ -450,8 +492,8 @@
void GenObjectHeader(const StructDef &struct_def) {
GenComment(struct_def.doc_comment);
- code_.SetValue("SHORT_STRUCTNAME", Name(struct_def));
- code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
+ code_.SetValue("SHORT_STRUCTNAME", namer_.Type(struct_def));
+ code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table");
code_.SetValue("MUTABLE", struct_def.fixed ? Mutable() : "");
code_ +=
@@ -468,12 +510,13 @@
if (!struct_def.fixed) {
if (parser_.file_identifier_.length()) {
code_.SetValue("FILENAME", parser_.file_identifier_);
+ code_ += "{{ACCESS_TYPE}} static var id: String { \"{{FILENAME}}\" } ";
code_ +=
"{{ACCESS_TYPE}} static func finish(_ fbb: inout "
"FlatBufferBuilder, end: "
"Offset, prefix: Bool = false) { fbb.finish(offset: end, "
"fileId: "
- "\"{{FILENAME}}\", addPrefix: prefix) }";
+ "{{STRUCTNAME}}.id, addPrefix: prefix) }";
}
code_ +=
"{{ACCESS_TYPE}} static func getRootAs{{SHORT_STRUCTNAME}}(bb: "
@@ -495,7 +538,7 @@
std::vector<std::string> require_fields;
std::vector<std::string> create_func_body;
std::vector<std::string> create_func_header;
- auto should_generate_create = struct_def.fields.vec.size() != 0;
+ const auto should_generate_create = struct_def.fields.vec.size() != 0;
code_.SetValue("NUMBEROFFIELDS", NumToString(struct_def.fields.vec.size()));
code_ +=
@@ -555,14 +598,12 @@
std::string spacing = "";
if (key_field != nullptr && !struct_def.fixed && struct_def.has_key) {
- code_.SetValue("VALUENAME", NameWrappedInNameSpace(struct_def));
- code_.SetValue("SHORT_VALUENAME", Name(struct_def));
code_.SetValue("VOFFSET", NumToString(key_field->value.offset));
- code_ +=
- "{{ACCESS_TYPE}} static func "
- "sortVectorOf{{SHORT_VALUENAME}}(offsets:[Offset], "
- "_ fbb: inout FlatBufferBuilder) -> Offset {";
+ code_ += "{{ACCESS_TYPE}} static func " +
+ namer_.Method("sort_vector_of", struct_def) +
+ "(offsets:[Offset], "
+ "_ fbb: inout FlatBufferBuilder) -> Offset {";
Indent();
code_ += spacing + "var off = offsets";
code_ +=
@@ -573,7 +614,7 @@
code_ += spacing + "return fbb.createVector(ofOffsets: off)";
Outdent();
code_ += "}";
- GenLookup(*key_field);
+ GenLookup(*key_field, namer_.NamespacedType(struct_def));
}
}
@@ -583,42 +624,44 @@
std::string builder_string = ", _ fbb: inout FlatBufferBuilder) { ";
auto &create_func_body = *create_body;
auto &create_func_header = *create_header;
- auto name = Name(field);
- auto type = GenType(field.value.type);
- auto opt_scalar =
+ const auto field_field = namer_.Field(field);
+ const auto field_var = namer_.Variable(field);
+ const auto type = GenType(field.value.type);
+ const auto opt_scalar =
field.IsOptional() && IsScalar(field.value.type.base_type);
- auto nullable_type = opt_scalar ? type + "?" : type;
- code_.SetValue("VALUENAME", name);
+ const auto nullable_type = opt_scalar ? type + "?" : type;
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
code_.SetValue("VALUETYPE", nullable_type);
- code_.SetValue("OFFSET", name);
+ code_.SetValue("OFFSET", namer_.Field(field));
code_.SetValue("CONSTANT", field.value.constant);
std::string check_if_vector =
(IsVector(field.value.type) || IsArray(field.value.type)) ? "VectorOf("
: "(";
- auto body = "add" + check_if_vector + name + ": ";
+ const auto body = "add" + check_if_vector + field_field + ": ";
code_ += "{{ACCESS_TYPE}} static func " + body + "\\";
- create_func_body.push_back("{{STRUCTNAME}}." + body + name + ", &fbb)");
+ create_func_body.push_back("{{STRUCTNAME}}." + body + field_field +
+ ", &fbb)");
if (IsScalar(field.value.type.base_type) &&
!IsBool(field.value.type.base_type)) {
- std::string is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
- std::string optional_enum =
+ const std::string is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
+ const std::string optional_enum =
IsEnum(field.value.type) ? ("?" + is_enum) : "";
code_ +=
- "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{VALUENAME}}\\";
+ "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{FIELDVAR}}\\";
code_ += field.IsOptional() ? (optional_enum + "\\")
: (is_enum + ", def: {{CONSTANT}}\\");
code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
- auto default_value =
+ const auto default_value =
IsEnum(field.value.type)
? (field.IsOptional() ? "nil" : GenEnumDefaultValue(field))
: field.value.constant;
create_func_header.push_back(
- "" + name + ": " + nullable_type + " = " +
+ "" + field_field + ": " + nullable_type + " = " +
(field.IsOptional() ? "nil" : default_value));
return;
}
@@ -629,48 +672,49 @@
code_.SetValue("CONSTANT", default_value);
code_.SetValue("VALUETYPE", field.IsOptional() ? "Bool?" : "Bool");
- code_ += "{{VALUETYPE}}" + builder_string +
- "fbb.add(element: {{VALUENAME}},\\";
+ code_ +=
+ "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{FIELDVAR}},\\";
code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},";
code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
create_func_header.push_back(
- name + ": " + nullable_type + " = " +
+ field_var + ": " + nullable_type + " = " +
(field.IsOptional() ? "nil" : default_value));
return;
}
if (IsStruct(field.value.type)) {
- auto create_struct =
- "guard let {{VALUENAME}} = {{VALUENAME}} else { return };"
- " fbb.create(struct: {{VALUENAME}}, position: "
+ const auto create_struct =
+ "guard let {{FIELDVAR}} = {{FIELDVAR}} else { return };"
+ " fbb.create(struct: {{FIELDVAR}}, position: "
"{{TABLEOFFSET}}.{{OFFSET}}.p) }";
code_ += type + "?" + builder_string + create_struct;
/// Optional hard coded since structs are always optional
- create_func_header.push_back(name + ": " + type + "? = nil");
+ create_func_header.push_back(field_var + ": " + type +
+ (field.IsOptional() ? "? = nil" : ""));
return;
}
- auto camel_case_name =
- ConvertCase(name, Case::kLowerCamel) +
+ const auto arg_label =
+ namer_.Variable(field) +
(IsVector(field.value.type) || IsArray(field.value.type)
? "VectorOffset"
: "Offset");
- create_func_header.push_back(camel_case_name + " " + name + ": " +
- "Offset = Offset()");
- auto reader_type =
+ create_func_header.push_back(arg_label + " " + field_var + ": " + "Offset" +
+ (field.IsRequired() ? "" : " = Offset()"));
+ const auto reader_type =
IsStruct(field.value.type) && field.value.type.struct_def->fixed
? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"
- : "offset: {{VALUENAME}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
+ : "offset: {{FIELDVAR}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
code_ += "Offset" + builder_string + "fbb.add(" + reader_type;
- auto vectortype = field.value.type.VectorType();
+ const auto vectortype = field.value.type.VectorType();
if ((vectortype.base_type == BASE_TYPE_STRUCT &&
field.value.type.struct_def->fixed) &&
(IsVector(field.value.type) || IsArray(field.value.type))) {
- auto field_name = NameWrappedInNameSpace(*vectortype.struct_def);
- code_ += "public static func startVectorOf" +
- ConvertCase(name, Case::kUpperCamel) +
+ const auto field_name = namer_.NamespacedType(*vectortype.struct_def);
+ code_ += "{{ACCESS_TYPE}} static func " +
+ namer_.Method("start_vector_of", field_var) +
"(_ size: Int, in builder: inout "
"FlatBufferBuilder) {";
Indent();
@@ -685,25 +729,26 @@
void GenTableReader(const StructDef &struct_def) {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
GenTableReaderFields(field);
}
}
void GenTableReaderFields(const FieldDef &field) {
- auto offset = NumToString(field.value.offset);
- auto name = Name(field);
- auto type = GenType(field.value.type);
- code_.SetValue("VALUENAME", name);
+ const auto offset = NumToString(field.value.offset);
+ const auto field_field = namer_.Field(field);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
+ code_.SetValue("FIELDMETHOD", namer_.Method(field));
code_.SetValue("VALUETYPE", type);
- code_.SetValue("OFFSET", name);
+ code_.SetValue("OFFSET", namer_.Constant(field.name));
code_.SetValue("CONSTANT", field.value.constant);
bool opt_scalar =
field.IsOptional() && IsScalar(field.value.type.base_type);
std::string def_Val = opt_scalar ? "nil" : "{{CONSTANT}}";
std::string optional = opt_scalar ? "?" : "";
- auto const_string = "return o == 0 ? " + def_Val + " : ";
+ const auto const_string = "return o == 0 ? " + def_Val + " : ";
GenComment(field.doc_comment);
if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) &&
!IsBool(field.value.type.base_type)) {
@@ -728,7 +773,7 @@
}
if (IsEnum(field.value.type)) {
- auto default_value =
+ const auto default_value =
field.IsOptional() ? "nil" : GenEnumDefaultValue(field);
code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
code_ += GenReaderMainBody(optional) + "\\";
@@ -739,16 +784,15 @@
return;
}
- std::string is_required = field.IsRequired() ? "!" : "?";
- auto required_reader = field.IsRequired() ? "return " : const_string;
+ const std::string is_required = field.IsRequired() ? "!" : "?";
+ const auto required_reader = field.IsRequired() ? "return " : const_string;
if (IsStruct(field.value.type) && field.value.type.struct_def->fixed) {
code_.SetValue("VALUETYPE", GenType(field.value.type));
code_.SetValue("CONSTANT", "nil");
code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader +
"{{ACCESS}}.readBuffer(of: {{VALUETYPE}}.self, at: o) }";
- code_.SetValue("VALUENAME",
- "mutable" + ConvertCase(name, Case::kUpperCamel));
+ code_.SetValue("FIELDVAR", namer_.Variable("mutable", field_field));
code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
code_.SetValue("CONSTANT", "nil");
code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader +
@@ -765,12 +809,12 @@
break;
case BASE_TYPE_STRING: {
- auto default_string = "\"" + field.value.constant + "\"";
+ const auto default_string = "\"" + field.value.constant + "\"";
code_.SetValue("VALUETYPE", GenType(field.value.type));
code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil");
code_ += GenReaderMainBody(is_required) + GenOffset() +
required_reader + "{{ACCESS}}.string(at: o) }";
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}SegmentArray: [UInt8]" +
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}SegmentArray: [UInt8]" +
is_required +
" { return "
"{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) }";
@@ -781,7 +825,7 @@
case BASE_TYPE_UNION:
code_.SetValue("CONSTANT", "nil");
code_ +=
- "{{ACCESS_TYPE}} func {{VALUENAME}}<T: "
+ "{{ACCESS_TYPE}} func {{FIELDVAR}}<T: "
"FlatbuffersInitializable>(type: "
"T.Type) -> T" +
is_required + " { " + GenOffset() + required_reader +
@@ -793,20 +837,22 @@
void GenTableReaderVectorFields(const FieldDef &field) {
std::string const_string = "return o == 0 ? {{CONSTANT}} : ";
- auto vectortype = field.value.type.VectorType();
+ const auto vectortype = field.value.type.VectorType();
code_.SetValue("SIZE", NumToString(InlineSize(vectortype)));
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}Count: Int32 { " + GenOffset() +
+ code_.SetValue("HAS_FIELDVAR", namer_.Variable("has", field));
+ code_ += "{{ACCESS_TYPE}} var {{HAS_FIELDVAR}}: Bool { " + GenOffset() +
+ "return o == 0 ? false : true }";
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}Count: Int32 { " + GenOffset() +
"return o == 0 ? 0 : {{ACCESS}}.vector(count: o) }";
- code_.SetValue("CONSTANT",
- IsScalar(vectortype.base_type) == true ? "0" : "nil");
- auto nullable = IsScalar(vectortype.base_type) == true ? "" : "?";
- nullable = IsEnum(vectortype) == true ? "?" : nullable;
+ code_.SetValue("CONSTANT", IsScalar(vectortype.base_type) ? "0" : "nil");
+ const auto nullable =
+ IsScalar(vectortype.base_type) && !IsEnum(vectortype) ? "" : "?";
if (vectortype.base_type != BASE_TYPE_UNION) {
code_ += GenArrayMainBody(nullable) + GenOffset() + "\\";
} else {
code_ +=
- "{{ACCESS_TYPE}} func {{VALUENAME}}<T: FlatbuffersInitializable>(at "
+ "{{ACCESS_TYPE}} func {{FIELDVAR}}<T: FlatbuffersInitializable>(at "
"index: "
"Int32, type: T.Type) -> T? { " +
GenOffset() + "\\";
@@ -825,7 +871,7 @@
"{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
"{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
code_ +=
- "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}] { return "
+ "{{ACCESS_TYPE}} var {{FIELDVAR}}: [{{VALUETYPE}}] { return "
"{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) ?? [] }";
if (parser_.opts.mutable_buffer) code_ += GenMutateArray();
return;
@@ -836,8 +882,7 @@
code_ +=
"{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
"{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
- code_.SetValue("VALUENAME",
- "mutable" + ConvertCase(Name(field), Case::kUpperCamel));
+ code_.SetValue("FIELDMETHOD", namer_.Method("mutable", field));
code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
code_ += GenArrayMainBody(nullable) + GenOffset() + const_string +
GenConstructor("{{ACCESS}}.vector(at: o) + index * {{SIZE}}");
@@ -872,10 +917,10 @@
code_ += GenConstructor(
"{{ACCESS}}.indirect({{ACCESS}}.vector(at: o) + index * "
"{{SIZE}})");
- auto &sd = *field.value.type.struct_def;
- auto &fields = sd.fields.vec;
+ const auto &sd = *field.value.type.struct_def;
+ const auto &fields = sd.fields.vec;
for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
- auto &key_field = **kit;
+ const auto &key_field = **kit;
if (key_field.key) {
GenByKeyFunctions(key_field);
break;
@@ -889,13 +934,12 @@
Indent();
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto name = Name(field);
code_.SetValue("RAWVALUENAME", field.name);
- code_.SetValue("VALUENAME", name);
- code_ += "case {{VALUENAME}} = \"{{RAWVALUENAME}}\"";
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
+ code_ += "case {{FIELDVAR}} = \"{{RAWVALUENAME}}\"";
}
Outdent();
code_ += "}";
@@ -903,8 +947,8 @@
void GenerateEncoderUnionBody(const FieldDef &field) {
EnumDef &union_def = *field.value.type.enum_def;
- auto is_vector = field.value.type.base_type == BASE_TYPE_VECTOR ||
- field.value.type.base_type == BASE_TYPE_ARRAY;
+ const auto is_vector = field.value.type.base_type == BASE_TYPE_VECTOR ||
+ field.value.type.base_type == BASE_TYPE_ARRAY;
if (field.value.type.base_type == BASE_TYPE_UTYPE ||
(is_vector &&
field.value.type.VectorType().base_type == BASE_TYPE_UTYPE))
@@ -912,28 +956,25 @@
if (is_vector) {
code_ +=
"var enumsEncoder = container.nestedUnkeyedContainer(forKey: "
- ".{{VALUENAME}}Type)";
+ ".{{FIELDVAR}}Type)";
code_ +=
"var contentEncoder = container.nestedUnkeyedContainer(forKey: "
- ".{{VALUENAME}})";
- code_ += "for index in 0..<{{VALUENAME}}Count {";
+ ".{{FIELDVAR}})";
+ code_ += "for index in 0..<{{FIELDVAR}}Count {";
Indent();
- code_ +=
- "guard let type = {{VALUENAME}}Type(at: index) else { continue }";
+ code_ += "guard let type = {{FIELDVAR}}Type(at: index) else { continue }";
code_ += "try enumsEncoder.encode(type)";
code_ += "switch type {";
for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
++it) {
const auto &ev = **it;
-
- auto name = Name(ev);
- auto type = GenType(ev.union_type);
- code_.SetValue("KEY", name);
+ const auto type = GenType(ev.union_type);
+ code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
code_.SetValue("VALUETYPE", type);
if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
code_ += "case .{{KEY}}:";
Indent();
- code_ += "let _v = {{VALUENAME}}(at: index, type: {{VALUETYPE}}.self)";
+ code_ += "let _v = {{FIELDVAR}}(at: index, type: {{VALUETYPE}}.self)";
code_ += "try contentEncoder.encode(_v)";
Outdent();
}
@@ -944,20 +985,18 @@
return;
}
- code_ += "switch {{VALUENAME}}Type {";
+ code_ += "switch {{FIELDVAR}}Type {";
for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
++it) {
const auto &ev = **it;
-
- auto name = Name(ev);
- auto type = GenType(ev.union_type);
- code_.SetValue("KEY", name);
+ const auto type = GenType(ev.union_type);
+ code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
code_.SetValue("VALUETYPE", type);
if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
code_ += "case .{{KEY}}:";
Indent();
- code_ += "let _v = {{VALUENAME}}(type: {{VALUETYPE}}.self)";
- code_ += "try container.encodeIfPresent(_v, forKey: .{{VALUENAME}})";
+ code_ += "let _v = {{FIELDVAR}}(type: {{VALUETYPE}}.self)";
+ code_ += "try container.encodeIfPresent(_v, forKey: .{{FIELDVAR}})";
Outdent();
}
code_ += "default: break;";
@@ -968,33 +1007,31 @@
code_ += "var container = encoder.container(keyedBy: CodingKeys.self)";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto name = Name(field);
- auto type = field.value.type;
+ const auto type = field.value.type;
- auto is_non_union_vector =
+ const auto is_non_union_vector =
(field.value.type.base_type == BASE_TYPE_ARRAY ||
field.value.type.base_type == BASE_TYPE_VECTOR) &&
field.value.type.VectorType().base_type != BASE_TYPE_UTYPE;
- code_.SetValue("RAWVALUENAME", field.name);
- code_.SetValue("VALUENAME", name);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
code_.SetValue("CONSTANT", field.value.constant);
bool should_indent = true;
if (is_non_union_vector) {
- code_ += "if {{VALUENAME}}Count > 0 {";
+ code_ += "if {{FIELDVAR}}Count > 0 {";
} else if (IsEnum(type) && !field.IsOptional()) {
code_.SetValue("CONSTANT", GenEnumDefaultValue(field));
- code_ += "if {{VALUENAME}} != {{CONSTANT}} {";
+ code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
} else if (IsScalar(type.base_type) && !IsEnum(type) &&
!IsBool(type.base_type) && !field.IsOptional()) {
- code_ += "if {{VALUENAME}} != {{CONSTANT}} {";
+ code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
} else if (IsBool(type.base_type) && !field.IsOptional()) {
std::string default_value =
"0" == field.value.constant ? "false" : "true";
code_.SetValue("CONSTANT", default_value);
- code_ += "if {{VALUENAME}} != {{CONSTANT}} {";
+ code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
} else {
should_indent = false;
}
@@ -1007,17 +1044,17 @@
IsEnum(type.VectorType()))) {
code_ +=
"var contentEncoder = container.nestedUnkeyedContainer(forKey: "
- ".{{VALUENAME}})";
- code_ += "for index in 0..<{{VALUENAME}}Count {";
+ ".{{FIELDVAR}})";
+ code_ += "for index in 0..<{{FIELDVAR}}Count {";
Indent();
- code_ += "guard let type = {{VALUENAME}}(at: index) else { continue }";
+ code_ += "guard let type = {{FIELDVAR}}(at: index) else { continue }";
code_ += "try contentEncoder.encode(type)";
Outdent();
code_ += "}";
} else {
code_ +=
- "try container.encodeIfPresent({{VALUENAME}}, forKey: "
- ".{{VALUENAME}})";
+ "try container.encodeIfPresent({{FIELDVAR}}, forKey: "
+ ".{{FIELDVAR}})";
}
if (should_indent) Outdent();
@@ -1034,7 +1071,7 @@
code_ += "";
if (struct_def.fields.vec.empty() == false) GenerateCodingKeys(struct_def);
- code_ += "public func encode(to encoder: Encoder) throws {";
+ code_ += "{{ACCESS_TYPE}} func encode(to encoder: Encoder) throws {";
Indent();
if (struct_def.fields.vec.empty() == false) GenerateEncoderBody(struct_def);
Outdent();
@@ -1046,20 +1083,20 @@
void GenerateVerifier(const StructDef &struct_def) {
code_ +=
- "public static func verify<T>(_ verifier: inout Verifier, at position: "
+ "{{ACCESS_TYPE}} static func verify<T>(_ verifier: inout Verifier, at "
+ "position: "
"Int, of type: T.Type) throws where T: Verifiable {";
Indent();
code_ += "var _v = try verifier.visitTable(at: position)";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto offset = NumToString(field.value.offset);
- auto name = Name(field);
+ const auto offset = NumToString(field.value.offset);
- code_.SetValue("VALUENAME", name);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
code_.SetValue("VALUETYPE", GenerateVerifierType(field));
- code_.SetValue("OFFSET", name);
+ code_.SetValue("OFFSET", namer_.Field(field));
code_.SetValue("ISREQUIRED", field.IsRequired() ? "true" : "false");
if (IsUnion(field.value.type)) {
@@ -1069,7 +1106,7 @@
code_ +=
"try _v.visit(field: {{TABLEOFFSET}}.{{OFFSET}}.p, fieldName: "
- "\"{{VALUENAME}}\", required: {{ISREQUIRED}}, type: "
+ "\"{{FIELDVAR}}\", required: {{ISREQUIRED}}, type: "
"{{VALUETYPE}}.self)";
}
code_ += "_v.finish()";
@@ -1078,28 +1115,27 @@
}
void GenerateUnionTypeVerifier(const FieldDef &field) {
- auto is_vector = IsVector(field.value.type) || IsArray(field.value.type);
+ const auto is_vector =
+ IsVector(field.value.type) || IsArray(field.value.type);
if (field.value.type.base_type == BASE_TYPE_UTYPE ||
(is_vector &&
field.value.type.VectorType().base_type == BASE_TYPE_UTYPE))
return;
EnumDef &union_def = *field.value.type.enum_def;
- code_.SetValue("VALUETYPE", NameWrappedInNameSpace(union_def));
+ code_.SetValue("VALUETYPE", namer_.NamespacedType(union_def));
code_.SetValue("FUNCTION_NAME", is_vector ? "visitUnionVector" : "visit");
code_ +=
"try _v.{{FUNCTION_NAME}}(unionKey: {{TABLEOFFSET}}.{{OFFSET}}Type.p, "
"unionField: {{TABLEOFFSET}}.{{OFFSET}}.p, unionKeyName: "
- "\"{{VALUENAME}}Type\", fieldName: \"{{VALUENAME}}\", required: "
+ "\"{{FIELDVAR}}Type\", fieldName: \"{{FIELDVAR}}\", required: "
"{{ISREQUIRED}}, completion: { (verifier, key: {{VALUETYPE}}, pos) in";
Indent();
code_ += "switch key {";
for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
++it) {
const auto &ev = **it;
-
- auto name = Name(ev);
- auto type = GenType(ev.union_type);
- code_.SetValue("KEY", name);
+ const auto type = GenType(ev.union_type);
+ code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
code_.SetValue("VALUETYPE", type);
code_ += "case .{{KEY}}:";
Indent();
@@ -1125,11 +1161,11 @@
}
std::string GenerateVerifierType(const FieldDef &field) {
- auto type = field.value.type;
- auto is_vector = IsVector(type) || IsArray(type);
+ const auto type = field.value.type;
+ const auto is_vector = IsVector(type) || IsArray(type);
if (is_vector) {
- auto vector_type = field.value.type.VectorType();
+ const auto vector_type = field.value.type.VectorType();
return "ForwardOffset<Vector<" +
GenerateNestedVerifierTypes(vector_type) + ", " +
GenType(vector_type) + ">>";
@@ -1139,7 +1175,7 @@
}
std::string GenerateNestedVerifierTypes(const Type &type) {
- auto string_type = GenType(type);
+ const auto string_type = GenType(type);
if (IsScalar(type.base_type)) { return string_type; }
@@ -1153,7 +1189,7 @@
void GenByKeyFunctions(const FieldDef &key_field) {
code_.SetValue("TYPE", GenType(key_field.value.type));
code_ +=
- "{{ACCESS_TYPE}} func {{VALUENAME}}By(key: {{TYPE}}) -> {{VALUETYPE}}? "
+ "{{ACCESS_TYPE}} func {{FIELDVAR}}By(key: {{TYPE}}) -> {{VALUETYPE}}? "
"{ \\";
code_ += GenOffset() +
"return o == 0 ? nil : {{VALUETYPE}}.lookupByKey(vector: "
@@ -1162,11 +1198,11 @@
void GenEnum(const EnumDef &enum_def) {
if (enum_def.generated) return;
- auto is_private_access = enum_def.attributes.Lookup("private");
+ const auto is_private_access = enum_def.attributes.Lookup("private");
code_.SetValue("ENUM_TYPE",
enum_def.is_union ? "UnionEnum" : "Enum, Verifiable");
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
- code_.SetValue("ENUM_NAME", NameWrappedInNameSpace(enum_def));
+ code_.SetValue("ENUM_NAME", namer_.NamespacedType(enum_def));
code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
GenComment(enum_def.doc_comment);
code_ +=
@@ -1189,15 +1225,16 @@
"{{ACCESS_TYPE}} var value: {{BASE_TYPE}} { return self.rawValue }";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
const auto &ev = **it;
- auto name = Name(ev);
- code_.SetValue("KEY", name);
+ code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
code_.SetValue("VALUE", enum_def.ToString(ev));
GenComment(ev.doc_comment);
code_ += "case {{KEY}} = {{VALUE}}";
}
code_ += "";
- AddMinOrMaxEnumValue(Name(*enum_def.MaxValue()), "max");
- AddMinOrMaxEnumValue(Name(*enum_def.MinValue()), "min");
+ AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MaxValue()),
+ "max");
+ AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MinValue()),
+ "min");
Outdent();
code_ += "}\n";
if (parser_.opts.gen_json_coders) EnumEncoder(enum_def);
@@ -1235,8 +1272,7 @@
code_ += "switch self {";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
const auto &ev = **it;
- auto name = Name(ev);
- code_.SetValue("KEY", name);
+ code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
code_.SetValue("RAWKEY", ev.name);
code_ += "case .{{KEY}}: try container.encode(\"{{RAWKEY}}\")";
}
@@ -1249,18 +1285,18 @@
// MARK: - Object API
- void GenerateObjectAPIExtensionHeader(std::string name) {
+ void GenerateObjectAPIExtensionHeader(std::string type_name) {
code_ += "\n";
- code_ += "{{ACCESS_TYPE}} mutating func unpack() -> " + name + " {";
+ code_ += "{{ACCESS_TYPE}} mutating func unpack() -> " + type_name + " {";
Indent();
- code_ += "return " + name + "(&self)";
+ code_ += "return " + type_name + "(&self)";
Outdent();
code_ += "}";
code_ +=
"{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
"obj: "
"inout " +
- name + "?) -> Offset {";
+ type_name + "?) -> Offset {";
Indent();
code_ += "guard var obj = obj else { return Offset() }";
code_ += "return pack(&builder, obj: &obj)";
@@ -1271,7 +1307,7 @@
"{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
"obj: "
"inout " +
- name + ") -> Offset {";
+ type_name + ") -> Offset {";
Indent();
}
@@ -1281,40 +1317,39 @@
Indent();
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto name = Name(field);
- auto type = GenType(field.value.type);
- code_.SetValue("VALUENAME", name);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
if (IsStruct(field.value.type)) {
- code_ += "var _v{{VALUENAME}} = _t.{{VALUENAME}}";
- code_ += "_{{VALUENAME}} = _v{{VALUENAME}}.unpack()";
+ code_ += "var _v{{FIELDVAR}} = _t.{{FIELDVAR}}";
+ code_ += "_{{FIELDVAR}} = _v{{FIELDVAR}}.unpack()";
continue;
}
std::string is_enum = IsEnum(field.value.type) ? ".value" : "";
- code_ += "_{{VALUENAME}} = _t.{{VALUENAME}}" + is_enum;
+ code_ += "_{{FIELDVAR}} = _t.{{FIELDVAR}}" + is_enum;
}
Outdent();
code_ += "}\n";
}
void GenObjectAPI(const StructDef &struct_def) {
- code_ += "{{ACCESS_TYPE}} class " + ObjectAPIName("{{STRUCTNAME}}") +
- ": NativeObject {\n";
+ code_ += "{{ACCESS_TYPE}} class " +
+ namer_.NamespacedObjectType(struct_def) + ": NativeObject {\n";
std::vector<std::string> buffer_constructor;
std::vector<std::string> base_constructor;
Indent();
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
BuildObjectAPIConstructorBody(field, struct_def.fixed, buffer_constructor,
base_constructor);
}
code_ += "";
BuildObjectConstructor(buffer_constructor,
- "_ _t: inout " + NameWrappedInNameSpace(struct_def));
+ "_ _t: inout " + namer_.NamespacedType(struct_def));
BuildObjectConstructor(base_constructor);
if (!struct_def.fixed)
code_ +=
@@ -1326,35 +1361,37 @@
}
void GenerateObjectAPITableExtension(const StructDef &struct_def) {
- GenerateObjectAPIExtensionHeader(ObjectAPIName("{{STRUCTNAME}}"));
+ GenerateObjectAPIExtensionHeader(namer_.NamespacedObjectType(struct_def));
std::vector<std::string> unpack_body;
std::string builder = ", &builder)";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto name = Name(field);
- auto type = GenType(field.value.type);
+ const auto field_var = namer_.Variable(field);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto type = GenType(field.value.type);
std::string check_if_vector =
(IsVector(field.value.type) || IsArray(field.value.type))
? "VectorOf("
: "(";
- std::string body = "add" + check_if_vector + name + ": ";
+ std::string body = "add" + check_if_vector + field_method + ": ";
switch (field.value.type.base_type) {
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
case BASE_TYPE_VECTOR: {
- GenerateVectorObjectAPITableExtension(field, name, type);
- unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
+ GenerateVectorObjectAPITableExtension(field);
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + field_var +
builder);
break;
}
case BASE_TYPE_UNION: {
- code_ += "let __" + name + " = obj." + name +
+ code_ += "let __" + field_var + " = obj." + field_var +
"?.pack(builder: &builder) ?? Offset()";
- unpack_body.push_back("if let o = obj." + name + "?.type {");
- unpack_body.push_back(" {{STRUCTNAME}}.add(" + name + "Type: o" +
- builder);
- unpack_body.push_back(" {{STRUCTNAME}}." + body + "__" + name +
+ unpack_body.push_back("if let o = obj." + field_var + "?.type {");
+ unpack_body.push_back(" {{STRUCTNAME}}.add(" + field_var +
+ "Type: o" + builder);
+ unpack_body.push_back(" {{STRUCTNAME}}." + body + "__" + field_var +
builder);
unpack_body.push_back("}\n");
break;
@@ -1368,31 +1405,31 @@
GenerateStructArgs(*field.value.type.struct_def, &code, "", "",
"$0", true);
code = code.substr(0, code.size() - 2);
- unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." + name +
- builder);
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." +
+ field_field + builder);
} else {
- code_ += "let __" + name + " = " + type +
- ".pack(&builder, obj: &obj." + name + ")";
- unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
+ code_ += "let __" + field_var + " = " + type +
+ ".pack(&builder, obj: &obj." + field_field + ")";
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + field_var +
builder);
}
break;
}
case BASE_TYPE_STRING: {
- unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + field_var +
builder);
if (field.IsRequired()) {
- code_ +=
- "let __" + name + " = builder.create(string: obj." + name + ")";
+ code_ += "let __" + field_var + " = builder.create(string: obj." +
+ field_field + ")";
} else {
- BuildingOptionalObjects(name, "builder.create(string: s)");
+ BuildingOptionalObjects(field_field, "builder.create(string: s)");
}
break;
}
case BASE_TYPE_UTYPE: break;
default:
- unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." + name +
- builder);
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." +
+ field_field + builder);
}
}
code_ += "let __root = {{STRUCTNAME}}.start{{SHORT_STRUCTNAME}}(&builder)";
@@ -1405,79 +1442,79 @@
code_ += "}";
}
- void GenerateVectorObjectAPITableExtension(const FieldDef &field,
- const std::string &name,
- const std::string &type) {
- auto vectortype = field.value.type.VectorType();
+ void GenerateVectorObjectAPITableExtension(const FieldDef &field_def) {
+ const Type &field_type = field_def.value.type;
+ const auto type = GenType(field_type);
+ const auto var = namer_.Variable(field_def);
+ const auto field = namer_.Field(field_def);
+
+ const auto vectortype = field_type.VectorType();
switch (vectortype.base_type) {
case BASE_TYPE_UNION: {
- code_ += "var __" + name + "__: [Offset] = []";
- code_ += "for i in obj." + name + " {";
+ code_ += "var __" + var + "__: [Offset] = []";
+ code_ += "for i in obj." + var + " {";
Indent();
code_ += "guard let off = i?.pack(builder: &builder) else { continue }";
- code_ += "__" + name + "__.append(off)";
+ code_ += "__" + var + "__.append(off)";
Outdent();
code_ += "}";
- code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
- name + "__)";
- code_ += "let __" + name + "Type = builder.createVector(obj." + name +
+ code_ += "let __" + var + " = builder.createVector(ofOffsets: __" +
+ var + "__)";
+ code_ += "let __" + var + "Type = builder.createVector(obj." + field +
".compactMap { $0?.type })";
break;
}
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_STRUCT: {
- if (field.value.type.struct_def &&
- !field.value.type.struct_def->fixed) {
- code_ += "var __" + name + "__: [Offset] = []";
- code_ += "for var i in obj." + name + " {";
+ if (field_type.struct_def && !field_type.struct_def->fixed) {
+ code_ += "var __" + var + "__: [Offset] = []";
+ code_ += "for var i in obj." + var + " {";
Indent();
code_ +=
- "__" + name + "__.append(" + type + ".pack(&builder, obj: &i))";
+ "__" + var + "__.append(" + type + ".pack(&builder, obj: &i))";
Outdent();
code_ += "}";
- code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
- name + "__)";
+ code_ += "let __" + var + " = builder.createVector(ofOffsets: __" +
+ var + "__)";
} else {
- code_ += "{{STRUCTNAME}}.startVectorOf" +
- ConvertCase(name, Case::kUpperCamel) + "(obj." + name +
- ".count, in: &builder)";
+ code_ += "{{STRUCTNAME}}." + namer_.Method("start_vector_of", var) +
+ "(obj." + field + ".count, in: &builder)";
std::string code;
- GenerateStructArgs(*field.value.type.struct_def, &code, "", "", "_o",
- true);
+ GenerateStructArgs(*field_type.struct_def, &code, "", "", "_o", true);
code = code.substr(0, code.size() - 2);
- code_ += "for i in obj." + name + " {";
+ code_ += "for i in obj." + field + " {";
Indent();
code_ += "guard let _o = i else { continue }";
code_ += "builder.create(struct: _o)";
Outdent();
code_ += "}";
- code_ += "let __" + name + " = builder.endVector(len: obj." + name +
+ code_ += "let __" + var + " = builder.endVector(len: obj." + field +
".count)";
}
break;
}
case BASE_TYPE_STRING: {
- code_ += "let __" + name + " = builder.createVector(ofStrings: obj." +
- name + ".compactMap({ $0 }) )";
+ code_ += "let __" + var + " = builder.createVector(ofStrings: obj." +
+ var + ".compactMap({ $0 }) )";
break;
}
default: {
- code_ += "let __" + name + " = builder.createVector(obj." + name + ")";
+ code_ += "let __" + var + " = builder.createVector(obj." + field + ")";
break;
}
}
}
- void BuildingOptionalObjects(const std::string &name,
+ void BuildingOptionalObjects(const std::string &var,
const std::string &body_front) {
- code_ += "let __" + name + ": Offset";
- code_ += "if let s = obj." + name + " {";
+ code_ += "let __" + var + ": Offset";
+ code_ += "if let s = obj." + var + " {";
Indent();
- code_ += "__" + name + " = " + body_front;
+ code_ += "__" + var + " = " + body_front;
Outdent();
code_ += "} else {";
Indent();
- code_ += "__" + name + " = Offset()";
+ code_ += "__" + var + " = Offset()";
Outdent();
code_ += "}";
code_ += "";
@@ -1497,120 +1534,125 @@
const FieldDef &field, bool is_fixed,
std::vector<std::string> &buffer_constructor,
std::vector<std::string> &base_constructor) {
- auto name = Name(field);
- auto type = GenType(field.value.type);
- code_.SetValue("VALUENAME", name);
+ const auto field_field = namer_.Field(field);
+ const auto field_var = namer_.Variable(field);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", field_field);
code_.SetValue("VALUETYPE", type);
std::string is_required = field.IsRequired() ? "" : "?";
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
- type = GenType(field.value.type, true);
- code_.SetValue("VALUETYPE", type);
- auto optional =
+ const auto objtype = GenType(field.value.type, true);
+ code_.SetValue("VALUETYPE", objtype);
+ const auto optional =
(field.value.type.struct_def && field.value.type.struct_def->fixed);
std::string question_mark =
(field.IsRequired() || (optional && is_fixed) ? "" : "?");
code_ +=
- "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + question_mark;
- base_constructor.push_back("" + name + " = " + type + "()");
+ "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + question_mark;
+ base_constructor.push_back("" + field_var + " = " + objtype + "()");
if (field.value.type.struct_def->fixed) {
- buffer_constructor.push_back("" + name + " = _t." + name);
+ buffer_constructor.push_back("" + field_var + " = _t." + field_field);
} else {
- buffer_constructor.push_back("var __" + name + " = _t." + name);
+ buffer_constructor.push_back("var __" + field_var + " = _t." +
+ field_field);
buffer_constructor.push_back(
- "" + name + " = __" + name +
+ "" + field_var + " = __" + field_var +
(field.IsRequired() ? "!" : question_mark) + ".unpack()");
}
break;
}
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
case BASE_TYPE_VECTOR: {
- BuildObjectAPIConstructorBodyVectors(field, name, buffer_constructor,
+ BuildObjectAPIConstructorBodyVectors(field, buffer_constructor,
base_constructor, " ");
break;
}
case BASE_TYPE_STRING: {
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: String" + is_required;
- buffer_constructor.push_back(name + " = _t." + name);
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: String" + is_required;
+ buffer_constructor.push_back(field_var + " = _t." + field_field);
if (field.IsRequired()) {
std::string default_value =
field.IsDefault() ? field.value.constant : "";
- base_constructor.push_back(name + " = \"" + default_value + "\"");
+ base_constructor.push_back(field_var + " = \"" + default_value +
+ "\"");
break;
}
if (field.IsDefault() && !field.IsRequired()) {
std::string value = field.IsDefault() ? field.value.constant : "nil";
- base_constructor.push_back(name + " = \"" + value + "\"");
+ base_constructor.push_back(field_var + " = \"" + value + "\"");
}
break;
}
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_UNION: {
- BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
+ BuildUnionEnumSwitchCase(*field.value.type.enum_def, field_var,
buffer_constructor);
break;
}
default: {
- buffer_constructor.push_back(name + " = _t." + name);
+ buffer_constructor.push_back(field_var + " = _t." + field_field);
std::string nullable = field.IsOptional() ? "?" : "";
if (IsScalar(field.value.type.base_type) &&
!IsBool(field.value.type.base_type) && !IsEnum(field.value.type)) {
- code_ +=
- "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + nullable;
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + nullable;
if (!field.IsOptional())
- base_constructor.push_back(name + " = " + field.value.constant);
+ base_constructor.push_back(field_var + " = " +
+ field.value.constant);
break;
}
if (IsEnum(field.value.type)) {
- auto default_value = IsEnum(field.value.type)
- ? GenEnumDefaultValue(field)
- : field.value.constant;
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}";
- base_constructor.push_back(name + " = " + default_value);
+ const auto default_value = IsEnum(field.value.type)
+ ? GenEnumDefaultValue(field)
+ : field.value.constant;
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}";
+ base_constructor.push_back(field_var + " = " + default_value);
break;
}
if (IsBool(field.value.type.base_type)) {
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: Bool" + nullable;
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: Bool" + nullable;
std::string default_value =
"0" == field.value.constant ? "false" : "true";
if (!field.IsOptional())
- base_constructor.push_back(name + " = " + default_value);
+ base_constructor.push_back(field_var + " = " + default_value);
}
}
}
}
void BuildObjectAPIConstructorBodyVectors(
- const FieldDef &field, const std::string &name,
- std::vector<std::string> &buffer_constructor,
+ const FieldDef &field, std::vector<std::string> &buffer_constructor,
std::vector<std::string> &base_constructor,
const std::string &indentation) {
- auto vectortype = field.value.type.VectorType();
+ const auto vectortype = field.value.type.VectorType();
+ const auto field_var = namer_.Field(field);
+ const auto field_field = namer_.Field(field);
if (vectortype.base_type != BASE_TYPE_UTYPE) {
- buffer_constructor.push_back(name + " = []");
- buffer_constructor.push_back("for index in 0..<_t." + name + "Count {");
- base_constructor.push_back(name + " = []");
+ buffer_constructor.push_back(field_var + " = []");
+ buffer_constructor.push_back("for index in 0..<_t." + field_field +
+ "Count {");
+ base_constructor.push_back(field_var + " = []");
}
switch (vectortype.base_type) {
case BASE_TYPE_STRUCT: {
code_.SetValue("VALUETYPE", GenType(vectortype, true));
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}?]";
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: [{{VALUETYPE}}?]";
if (!vectortype.struct_def->fixed) {
- buffer_constructor.push_back(indentation + "var __v_ = _t." + name +
- "(at: index)");
- buffer_constructor.push_back(indentation + name +
+ buffer_constructor.push_back(indentation + "var __v_ = _t." +
+ field_field + "(at: index)");
+ buffer_constructor.push_back(indentation + field_var +
".append(__v_?.unpack())");
} else {
- buffer_constructor.push_back(indentation + name + ".append(_t." +
- name + "(at: index))");
+ buffer_constructor.push_back(indentation + field_var + ".append(_t." +
+ field_var + "(at: index))");
}
break;
}
@@ -1619,7 +1661,7 @@
break;
}
case BASE_TYPE_UNION: {
- BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
+ BuildUnionEnumSwitchCase(*field.value.type.enum_def, field_var,
buffer_constructor, indentation, true);
break;
}
@@ -1628,18 +1670,18 @@
code_.SetValue(
"VALUETYPE",
(IsString(vectortype) ? "String?" : GenType(vectortype)));
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}]";
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: [{{VALUETYPE}}]";
if (IsEnum(vectortype) && vectortype.base_type != BASE_TYPE_UNION) {
- auto default_value = IsEnum(field.value.type)
- ? GenEnumDefaultValue(field)
- : field.value.constant;
- buffer_constructor.push_back(indentation + name + ".append(_t." +
- name + "(at: index)!)");
+ const auto default_value = IsEnum(field.value.type)
+ ? GenEnumDefaultValue(field)
+ : field.value.constant;
+ buffer_constructor.push_back(indentation + field_var + ".append(_t." +
+ field_field + "(at: index)!)");
break;
}
- buffer_constructor.push_back(indentation + name + ".append(_t." + name +
- "(at: index))");
+ buffer_constructor.push_back(indentation + field_var + ".append(_t." +
+ field_field + "(at: index))");
break;
}
}
@@ -1647,19 +1689,17 @@
buffer_constructor.push_back("}");
}
- void BuildUnionEnumSwitchCaseWritter(const EnumDef &ev) {
- auto field_name = Name(ev);
- code_.SetValue("VALUETYPE", field_name);
+ void BuildUnionEnumSwitchCaseWritter(const EnumDef &ed) {
code_ += "switch type {";
- for (auto it = ev.Vals().begin(); it < ev.Vals().end(); ++it) {
- auto field = **it;
- auto ev_name = Name(field);
- auto type = GenType(field.union_type);
- auto is_struct = IsStruct(field.union_type) ? type + Mutable() : type;
- if (field.union_type.base_type == BASE_TYPE_NONE) { continue; }
- code_ += "case ." + ev_name + ":";
+ for (auto it = ed.Vals().begin(); it < ed.Vals().end(); ++it) {
+ const auto ev = **it;
+ const auto variant = namer_.LegacySwiftVariant(ev);
+ const auto type = GenType(ev.union_type);
+ const auto is_struct = IsStruct(ev.union_type) ? type + Mutable() : type;
+ if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ code_ += "case ." + variant + ":";
Indent();
- code_ += "var __obj = value as? " + GenType(field.union_type, true);
+ code_ += "var __obj = value as? " + GenType(ev.union_type, true);
code_ += "return " + is_struct + ".pack(&builder, obj: &__obj)";
Outdent();
}
@@ -1667,34 +1707,34 @@
code_ += "}";
}
- void BuildUnionEnumSwitchCase(const EnumDef &ev, const std::string &name,
+ void BuildUnionEnumSwitchCase(const EnumDef &ed, const std::string &field,
std::vector<std::string> &buffer_constructor,
const std::string &indentation = "",
const bool is_vector = false) {
- auto field_name = NameWrappedInNameSpace(ev);
- code_.SetValue("VALUETYPE", field_name);
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: \\";
+ const auto ns_type = namer_.NamespacedType(ed);
+ code_.SetValue("VALUETYPE", ns_type);
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: \\";
code_ += is_vector ? "[{{VALUETYPE}}Union?]" : "{{VALUETYPE}}Union?";
- auto vector_reader = is_vector ? "(at: index" : "";
- buffer_constructor.push_back(indentation + "switch _t." + name + "Type" +
+ const auto vector_reader = is_vector ? "(at: index" : "";
+ buffer_constructor.push_back(indentation + "switch _t." + field + "Type" +
vector_reader + (is_vector ? ")" : "") + " {");
- for (auto it = ev.Vals().begin(); it < ev.Vals().end(); ++it) {
- auto field = **it;
- auto ev_name = Name(field);
- if (field.union_type.base_type == BASE_TYPE_NONE) { continue; }
- auto type = IsStruct(field.union_type)
- ? GenType(field.union_type) + Mutable()
- : GenType(field.union_type);
- buffer_constructor.push_back(indentation + "case ." + ev_name + ":");
+ for (auto it = ed.Vals().begin(); it < ed.Vals().end(); ++it) {
+ const auto ev = **it;
+ const auto variant = namer_.LegacySwiftVariant(ev);
+ if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ const auto type = IsStruct(ev.union_type)
+ ? GenType(ev.union_type) + Mutable()
+ : GenType(ev.union_type);
+ buffer_constructor.push_back(indentation + "case ." + variant + ":");
buffer_constructor.push_back(
- indentation + " var _v = _t." + name + (is_vector ? "" : "(") +
+ indentation + " var _v = _t." + field + (is_vector ? "" : "(") +
vector_reader + (is_vector ? ", " : "") + "type: " + type + ".self)");
- auto constructor =
- field_name + "Union(_v?.unpack(), type: ." + ev_name + ")";
+ const auto constructor =
+ ns_type + "Union(_v?.unpack(), type: ." + variant + ")";
buffer_constructor.push_back(
- indentation + " " + name +
+ indentation + " " + field +
(is_vector ? ".append(" + constructor + ")" : " = " + constructor));
}
buffer_constructor.push_back(indentation + "default: break");
@@ -1702,13 +1742,14 @@
}
void AddMinOrMaxEnumValue(const std::string &str, const std::string &type) {
- auto current_value = str;
+ const auto current_value = str;
code_.SetValue(type, current_value);
code_ += "{{ACCESS_TYPE}} static var " + type +
": {{ENUM_NAME}} { return .{{" + type + "}} }";
}
- void GenLookup(const FieldDef &key_field) {
+ void GenLookup(const FieldDef &key_field, const std::string &struct_type) {
+ code_.SetValue("STRUCTTYPE", struct_type);
code_.SetValue("OFFSET", NumToString(key_field.value.offset));
std::string offset_reader =
"Table.offset(Int32(fbb.capacity) - tableOffset, vOffset: {{OFFSET}}, "
@@ -1718,7 +1759,7 @@
code_ +=
"fileprivate static func lookupByKey(vector: Int32, key: {{TYPE}}, "
"fbb: "
- "ByteBuffer) -> {{VALUENAME}}? {";
+ "ByteBuffer) -> {{STRUCTTYPE}}? {";
Indent();
if (IsString(key_field.value.type))
code_ += "let key = key.utf8.map { $0 }";
@@ -1748,7 +1789,7 @@
Outdent();
code_ += "} else {";
Indent();
- code_ += "return {{VALUENAME}}(fbb, o: tableOffset)";
+ code_ += "return {{STRUCTTYPE}}(fbb, o: tableOffset)";
Outdent();
code_ += "}";
Outdent();
@@ -1762,7 +1803,7 @@
if (field.padding) {
for (int i = 0; i < 4; i++) {
if (static_cast<int>(field.padding) & (1 << i)) {
- auto bits = (1 << i) * 8;
+ const auto bits = (1 << i) * 8;
code_ += "private let padding" + NumToString((*id)++) + "__: UInt" +
NumToString(bits) + " = 0";
}
@@ -1784,8 +1825,7 @@
}
std::string GenReaderMainBody(const std::string &optional = "") {
- return "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + optional +
- " { ";
+ return "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + optional + " { ";
}
std::string GenReader(const std::string &type,
@@ -1799,36 +1839,33 @@
std::string GenMutate(const std::string &offset,
const std::string &get_offset, bool isRaw = false) {
- return "@discardableResult {{ACCESS_TYPE}} func mutate({{VALUENAME}}: "
+ return "@discardableResult {{ACCESS_TYPE}} func mutate({{FIELDVAR}}: "
"{{VALUETYPE}}) -> Bool {" +
- get_offset + " return {{ACCESS}}.mutate({{VALUENAME}}" +
+ get_offset + " return {{ACCESS}}.mutate({{FIELDVAR}}" +
(isRaw ? ".rawValue" : "") + ", index: " + offset + ") }";
}
std::string GenMutateArray() {
- return "{{ACCESS_TYPE}} func mutate({{VALUENAME}}: {{VALUETYPE}}, at "
- "index: "
- "Int32) -> Bool { " +
+ return "{{ACCESS_TYPE}} func mutate({{FIELDVAR}}: {{VALUETYPE}}, at "
+ "index: Int32) -> Bool { " +
GenOffset() +
- "return {{ACCESS}}.directMutate({{VALUENAME}}, index: "
+ "return {{ACCESS}}.directMutate({{FIELDVAR}}, index: "
"{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
}
std::string GenEnumDefaultValue(const FieldDef &field) {
- auto &value = field.value;
+ const auto &value = field.value;
FLATBUFFERS_ASSERT(value.type.enum_def);
- auto &enum_def = *value.type.enum_def;
+ const auto &enum_def = *value.type.enum_def;
// Vector of enum defaults are always "[]" which never works.
const std::string constant = IsVector(value.type) ? "0" : value.constant;
- auto enum_val = enum_def.FindByValue(constant);
- std::string name;
+ const auto enum_val = enum_def.FindByValue(constant);
if (enum_val) {
- name = Name(*enum_val);
+ return "." + namer_.LegacySwiftVariant(*enum_val);
} else {
const auto &ev = **enum_def.Vals().begin();
- name = Name(ev);
+ return "." + namer_.LegacySwiftVariant(ev);
}
- return "." + name;
}
std::string GenEnumConstructor(const std::string &at) {
@@ -1836,15 +1873,14 @@
}
std::string ValidateFunc() {
- return "static func validateVersion() { FlatBuffersVersion_2_0_0() }";
+ return "static func validateVersion() { FlatBuffersVersion_2_0_8() }";
}
std::string GenType(const Type &type,
const bool should_consider_suffix = false) const {
- return IsScalar(type.base_type)
- ? GenTypeBasic(type)
- : (IsArray(type) ? GenType(type.VectorType())
- : GenTypePointer(type, should_consider_suffix));
+ return IsScalar(type.base_type) ? GenTypeBasic(type)
+ : IsArray(type) ? GenType(type.VectorType())
+ : GenTypePointer(type, should_consider_suffix);
}
std::string GenTypePointer(const Type &type,
@@ -1853,12 +1889,11 @@
case BASE_TYPE_STRING: return "String";
case BASE_TYPE_VECTOR: return GenType(type.VectorType());
case BASE_TYPE_STRUCT: {
- auto &struct_ = *type.struct_def;
- if (should_consider_suffix && !struct_.fixed) {
- return WrapInNameSpace(struct_.defined_namespace,
- ObjectAPIName(Name(struct_)));
+ const auto &sd = *type.struct_def;
+ if (should_consider_suffix && !sd.fixed) {
+ return namer_.NamespacedObjectType(sd);
}
- return WrapInNameSpace(struct_.defined_namespace, Name(struct_));
+ return namer_.NamespacedType(sd);
}
case BASE_TYPE_UNION:
default: return "FlatbuffersInitializable";
@@ -1869,22 +1904,10 @@
return GenTypeBasic(type, true);
}
- std::string ObjectAPIName(const std::string &name) const {
- return parser_.opts.object_prefix + name + parser_.opts.object_suffix;
- }
-
void Indent() { code_.IncrementIdentLevel(); }
void Outdent() { code_.DecrementIdentLevel(); }
- std::string NameWrappedInNameSpace(const EnumDef &enum_def) const {
- return WrapInNameSpace(enum_def.defined_namespace, Name(enum_def));
- }
-
- std::string NameWrappedInNameSpace(const StructDef &struct_def) const {
- return WrapInNameSpace(struct_def.defined_namespace, Name(struct_def));
- }
-
std::string GenTypeBasic(const Type &type, bool can_override) const {
// clang-format off
static const char * const swift_type[] = {
@@ -1896,29 +1919,15 @@
};
// clang-format on
if (can_override) {
- if (type.enum_def) return NameWrappedInNameSpace(*type.enum_def);
+ if (type.enum_def) return namer_.NamespacedType(*type.enum_def);
if (type.base_type == BASE_TYPE_BOOL) return "Bool";
}
return swift_type[static_cast<int>(type.base_type)];
}
- std::string EscapeKeyword(const std::string &name) const {
- return keywords_.find(name) == keywords_.end() ? name : name + "_";
- }
-
std::string Mutable() const { return "_Mutable"; }
- std::string Name(const EnumVal &ev) const {
- auto name = ev.name;
- if (isupper(name.front())) {
- std::transform(name.begin(), name.end(), name.begin(), CharToLower);
- }
- return EscapeKeyword(ConvertCase(name, Case::kLowerCamel));
- }
-
- std::string Name(const Definition &def) const {
- return EscapeKeyword(ConvertCase(def.name, Case::kLowerCamel));
- }
+ IdlNamer namer_;
};
} // namespace swift
bool GenerateSwift(const Parser &parser, const std::string &path,
diff --git a/third_party/flatbuffers/src/idl_gen_text.cpp b/third_party/flatbuffers/src/idl_gen_text.cpp
index 805e934..3b69c95 100644
--- a/third_party/flatbuffers/src/idl_gen_text.cpp
+++ b/third_party/flatbuffers/src/idl_gen_text.cpp
@@ -248,11 +248,23 @@
template<typename T>
bool GenField(const FieldDef &fd, const Table *table, bool fixed,
int indent) {
- return PrintScalar(
- fixed ? reinterpret_cast<const Struct *>(table)->GetField<T>(
- fd.value.offset)
- : table->GetField<T>(fd.value.offset, GetFieldDefault<T>(fd)),
- fd.value.type, indent);
+ if (fixed) {
+ return 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);
+ } else {
+ text += "null";
+ return true;
+ }
+ } else {
+ return PrintScalar(
+ table->GetField<T>(fd.value.offset, GetFieldDefault<T>(fd)),
+ fd.value.type, indent);
+ }
}
// Generate text for non-scalar field.
diff --git a/third_party/flatbuffers/src/idl_gen_ts.cpp b/third_party/flatbuffers/src/idl_gen_ts.cpp
index b97154c..32ab863 100644
--- a/third_party/flatbuffers/src/idl_gen_ts.cpp
+++ b/third_party/flatbuffers/src/idl_gen_ts.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-// independent from idl_parser, since this code is not needed for most clients
#include <algorithm>
#include <cassert>
#include <unordered_map>
@@ -24,21 +23,67 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
-
+namespace {
struct ImportDefinition {
std::string name;
std::string import_statement;
std::string export_statement;
std::string bare_file_path;
std::string rel_file_path;
+ std::string object_name;
const Definition *dependent = nullptr;
const Definition *dependency = nullptr;
};
+Namer::Config TypeScriptDefaultConfig() {
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kUnknown,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kLowerCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/"::",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"_",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kDasher,
+ /*directories=*/Case::kDasher,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".ts" };
+}
+
+std::set<std::string> TypescriptKeywords() {
+ // List of keywords retrieved from here:
+ // https://github.com/microsoft/TypeScript/issues/2536
+ return {
+ "arguments", "break", "case", "catch", "class", "const",
+ "continue", "debugger", "default", "delete", "do", "else",
+ "enum", "export", "extends", "false", "finally", "for",
+ "function", "if", "import", "in", "instanceof", "new",
+ "null", "Object", "return", "super", "switch", "this",
+ "throw", "true", "try", "typeof", "var", "void",
+ "while", "with", "as", "implements", "interface", "let",
+ "package", "private", "protected", "public", "static", "yield",
+ };
+}
+
enum AnnotationType { kParam = 0, kType = 1, kReturns = 2 };
+template<typename T> struct SupportsObjectAPI : std::false_type {};
+
+template<> struct SupportsObjectAPI<StructDef> : std::true_type {};
+
+} // namespace
+
namespace ts {
// Iterate through all definitions we haven't generate code for (enums, structs,
// and tables) and output them to a single file.
@@ -48,83 +93,53 @@
TsGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
- : BaseGenerator(parser, path, file_name, "", ".", "ts") {
- // clang-format off
+ : BaseGenerator(parser, path, file_name, "", "_", "ts"),
+ namer_(WithFlagOptions(TypeScriptDefaultConfig(), parser.opts, path),
+ TypescriptKeywords()) {}
- // List of keywords retrieved from here:
- // https://github.com/microsoft/TypeScript/issues/2536
- // One per line to ease comparisons to that list are easier
- static const char *const keywords[] = {
- "argument",
- "break",
- "case",
- "catch",
- "class",
- "const",
- "continue",
- "debugger",
- "default",
- "delete",
- "do",
- "else",
- "enum",
- "export",
- "extends",
- "false",
- "finally",
- "for",
- "function",
- "if",
- "import",
- "in",
- "instanceof",
- "new",
- "null",
- "Object",
- "return",
- "super",
- "switch",
- "this",
- "throw",
- "true",
- "try",
- "typeof",
- "var",
- "void",
- "while",
- "with",
- "as",
- "implements",
- "interface",
- "let",
- "package",
- "private",
- "protected",
- "public",
- "static",
- "yield",
- nullptr,
- // clang-format on
- };
-
- for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
- }
bool generate() {
- if (parser_.opts.ts_flat_file && parser_.opts.generate_all) {
- // Not implemented; warning message should have beem emitted by flatc.
- return false;
- }
generateEnums();
generateStructs();
generateEntry();
return true;
}
+ bool IncludeNamespace() const {
+ // When generating a single flat file and all its includes, namespaces are
+ // important to avoid type name clashes.
+ return parser_.opts.ts_flat_file && parser_.opts.generate_all;
+ }
+
+ std::string GetTypeName(const EnumDef &def, const bool = false,
+ const bool force_ns_wrap = false) {
+ if (IncludeNamespace() || force_ns_wrap) {
+ return namer_.NamespacedType(def);
+ }
+ return namer_.Type(def);
+ }
+
+ std::string GetTypeName(const StructDef &def, const bool object_api = false,
+ const bool force_ns_wrap = false) {
+ if (object_api && parser_.opts.generate_object_based_api) {
+ if (IncludeNamespace() || force_ns_wrap) {
+ return namer_.NamespacedObjectType(def);
+ } else {
+ return namer_.ObjectType(def);
+ }
+ } else {
+ if (IncludeNamespace() || force_ns_wrap) {
+ return namer_.NamespacedType(def);
+ } else {
+ return namer_.Type(def);
+ }
+ }
+ }
+
// Save out the generated code for a single class while adding
// declaration boilerplate.
- bool SaveType(const Definition &definition, const std::string &classcode,
+ bool SaveType(const Definition &definition, const std::string &class_code,
import_set &imports, import_set &bare_imports) {
- if (!classcode.length()) return true;
+ if (!class_code.length()) return true;
std::string code;
@@ -144,25 +159,24 @@
if (!imports.empty()) code += "\n\n";
}
- code += classcode;
- auto filename =
- NamespaceDir(*definition.defined_namespace, true) +
- ConvertCase(definition.name, Case::kDasher, Case::kUpperCamel) + ".ts";
+ code += class_code;
+
if (parser_.opts.ts_flat_file) {
flat_file_ += code;
+ flat_file_ += "\n";
flat_file_definitions_.insert(&definition);
return true;
} else {
- return SaveFile(filename.c_str(), code, false);
+ auto dirs = namer_.Directories(*definition.defined_namespace);
+ EnsureDirExists(dirs);
+ auto basename = dirs + namer_.File(definition, SkipFile::Suffix);
+
+ return SaveFile(basename.c_str(), code, false);
}
}
private:
- std::unordered_set<std::string> keywords_;
-
- std::string EscapeKeyword(const std::string &name) const {
- return keywords_.find(name) == keywords_.end() ? name : name + "_";
- }
+ IdlNamer namer_;
import_set imports_all_;
@@ -177,6 +191,10 @@
// This maps from import names to types to import.
std::map<std::string, std::map<std::string, std::string>>
flat_file_import_declarations_;
+ // For flat file codegen, tracks whether we need to import the flatbuffers
+ // library itself (not necessary for files that solely consist of enum
+ // definitions).
+ bool import_flatbuffers_lib_ = false;
// Generate code for all enums.
void generateEnums() {
@@ -200,6 +218,7 @@
import_set bare_imports;
import_set imports;
AddImport(bare_imports, "* as flatbuffers", "flatbuffers");
+ import_flatbuffers_lib_ = true;
auto &struct_def = **it;
std::string declcode;
GenStruct(parser_, struct_def, &declcode, imports);
@@ -210,38 +229,45 @@
// Generate code for a single entry point module.
void generateEntry() {
- std::string code;
+ std::string code =
+ "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
if (parser_.opts.ts_flat_file) {
- code += "import * as flatbuffers from 'flatbuffers';\n";
- for (const auto &it : flat_file_import_declarations_) {
- // Note that we do end up generating an import for ourselves, which
- // should generally be harmless.
- // TODO: Make it so we don't generate a self-import; this will also
- // require modifying AddImport to ensure that we don't use
- // namespace-prefixed names anywhere...
- std::string file = it.first;
- if (file.empty()) {
- continue;
- }
- std::string noext = flatbuffers::StripExtension(file);
- std::string basename = flatbuffers::StripPath(noext);
- std::string include_file = GeneratedFileName(
- parser_.opts.include_prefix,
- parser_.opts.keep_include_path ? noext : basename, parser_.opts);
- // TODO: what is the right behavior when different include flags are
- // specified here? Should we always be adding the "./" for a relative
- // path or turn it off if --include-prefix is specified, or something
- // else?
- std::string include_name = "./" + flatbuffers::StripExtension(include_file);
- code += "import {";
- for (const auto &pair : it.second) {
- code += EscapeKeyword(pair.first) + " as " +
- EscapeKeyword(pair.second) + ", ";
- }
- code.resize(code.size() - 2);
- code += "} from '" + include_name + "';\n";
+ if (import_flatbuffers_lib_) {
+ code += "import * as flatbuffers from 'flatbuffers';\n";
+ code += "\n";
}
- code += "\n\n";
+ // Only include import statements when not generating all.
+ if (!parser_.opts.generate_all) {
+ for (const auto &it : flat_file_import_declarations_) {
+ // Note that we do end up generating an import for ourselves, which
+ // should generally be harmless.
+ // TODO: Make it so we don't generate a self-import; this will also
+ // require modifying AddImport to ensure that we don't use
+ // namespace-prefixed names anywhere...
+ std::string file = it.first;
+ if (file.empty()) { continue; }
+ std::string noext = flatbuffers::StripExtension(file);
+ std::string basename = flatbuffers::StripPath(noext);
+ std::string include_file = GeneratedFileName(
+ parser_.opts.include_prefix,
+ parser_.opts.keep_prefix ? noext : basename, parser_.opts);
+ // TODO: what is the right behavior when different include flags are
+ // specified here? Should we always be adding the "./" for a relative
+ // path or turn it off if --include-prefix is specified, or something
+ // else?
+ std::string include_name =
+ "./" + flatbuffers::StripExtension(include_file);
+ code += "import {";
+ for (const auto &pair : it.second) {
+ code += namer_.EscapeKeyword(pair.first) + " as " +
+ namer_.EscapeKeyword(pair.second) + ", ";
+ }
+ code.resize(code.size() - 2);
+ code += "} from '" + include_name + ".js';\n";
+ }
+ code += "\n";
+ }
+
code += flat_file_;
const std::string filename =
GeneratedFileName(path_, file_name_, parser_.opts);
@@ -250,7 +276,8 @@
for (auto it = imports_all_.begin(); it != imports_all_.end(); it++) {
code += it->second.export_statement + "\n";
}
- std::string path = "./" + path_ + file_name_ + ".ts";
+ const std::string path =
+ GeneratedFileName(path_, file_name_, parser_.opts);
SaveFile(path.c_str(), code, false);
}
}
@@ -286,7 +313,9 @@
if (reverse) return; // FIXME.
std::string &code = *code_ptr;
GenDocComment(enum_def.doc_comment, code_ptr);
- code += "export enum " + EscapeKeyword(enum_def.name) + "{\n";
+ code += "export enum ";
+ code += GetTypeName(enum_def);
+ code += " {\n";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
if (!ev.doc_comment.empty()) {
@@ -294,15 +323,13 @@
GenDocComment(ev.doc_comment, code_ptr, " ");
}
- const std::string escaped_name = EscapeKeyword(ev.name);
-
// Generate mapping between EnumName: EnumValue(int)
if (reverse) {
code += " '" + enum_def.ToString(ev) + "'";
code += " = ";
- code += "'" + escaped_name + "'";
+ code += "'" + namer_.Variant(ev) + "'";
} else {
- code += " " + escaped_name;
+ code += " " + namer_.Variant(ev);
code += " = ";
// Unfortunately, because typescript does not support bigint enums,
// for 64-bit enums, we instead map the enum names to strings.
@@ -324,7 +351,7 @@
code += GenUnionConvFunc(enum_def.underlying_type, imports);
}
- code += "\n\n";
+ code += "\n";
}
static std::string GenType(const Type &type) {
@@ -359,8 +386,8 @@
return GenBBAccess() + ".__union_with_string" + arguments;
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType(), arguments);
default: {
- auto getter = GenBBAccess() + ".read" +
- ConvertCase(GenType(type), Case::kUpperCamel) + arguments;
+ auto getter = GenBBAccess() + "." +
+ namer_.Method("read_" + GenType(type)) + arguments;
if (type.base_type == BASE_TYPE_BOOL) { getter = "!!" + getter; }
return getter;
}
@@ -385,9 +412,10 @@
}
default: {
if (auto val = value.type.enum_def->FindByValue(value.constant)) {
- return EscapeKeyword(AddImport(imports, *value.type.enum_def,
- *value.type.enum_def)) +
- "." + EscapeKeyword(val->name);
+ return AddImport(imports, *value.type.enum_def,
+ *value.type.enum_def)
+ .name +
+ "." + namer_.Variant(*val);
} else {
return value.constant;
}
@@ -411,7 +439,9 @@
return "BigInt('" + value.constant + "')";
}
- default: return value.constant;
+ default:
+ if (value.constant == "nan") { return "NaN"; }
+ return value.constant;
}
}
@@ -424,7 +454,7 @@
if (IsString(type)) {
name = "string|Uint8Array";
} else {
- name = EscapeKeyword(AddImport(imports, owner, *type.struct_def));
+ name = AddImport(imports, owner, *type.struct_def).name;
}
return allowNull ? (name + "|null") : name;
}
@@ -437,7 +467,8 @@
default:
if (IsScalar(type.base_type)) {
if (type.enum_def) {
- const auto enum_name = AddImport(imports, owner, *type.enum_def);
+ const auto enum_name =
+ AddImport(imports, owner, *type.enum_def).name;
return allowNull ? (enum_name + "|null") : enum_name;
}
return allowNull ? "number|null" : "number";
@@ -447,7 +478,7 @@
}
// Returns the method name for use with add/put calls.
- static std::string GenWriteMethod(const Type &type) {
+ std::string GenWriteMethod(const Type &type) {
// Forward to signed versions since unsigned versions don't exist
switch (type.base_type) {
case BASE_TYPE_UTYPE:
@@ -458,9 +489,8 @@
default: break;
}
- return IsScalar(type.base_type)
- ? ConvertCase(GenType(type), Case::kUpperCamel)
- : (IsStruct(type) ? "Struct" : "Offset");
+ return IsScalar(type.base_type) ? namer_.Type(GenType(type))
+ : (IsStruct(type) ? "Struct" : "Offset");
}
template<typename T> static std::string MaybeAdd(T value) {
@@ -490,8 +520,8 @@
}
}
- static void GenStructBody(const StructDef &struct_def, std::string *body,
- const std::string &nameprefix) {
+ void GenStructBody(const StructDef &struct_def, std::string *body,
+ const std::string &nameprefix) {
*body += " builder.prep(";
*body += NumToString(struct_def.minalign) + ", ";
*body += NumToString(struct_def.bytesize) + ");\n";
@@ -517,7 +547,7 @@
}
std::string GenerateNewExpression(const std::string &object_name) {
- return "new " + EscapeKeyword(object_name) + "()";
+ return "new " + namer_.Type(object_name) + "()";
}
void GenerateRootAccessor(StructDef &struct_def, std::string *code_ptr,
@@ -563,16 +593,6 @@
}
}
- static std::string GetObjApiClassName(const StructDef &sd,
- const IDLOptions &opts) {
- return GetObjApiClassName(sd.name, opts);
- }
-
- static std::string GetObjApiClassName(const std::string &name,
- const IDLOptions &opts) {
- return opts.object_prefix + name + opts.object_suffix;
- }
-
bool UnionHasStringType(const EnumDef &union_enum) {
return std::any_of(union_enum.Vals().begin(), union_enum.Vals().end(),
[](const EnumVal *ev) {
@@ -601,7 +621,7 @@
if (IsString(ev.union_type)) {
type = "string"; // no need to wrap string type in namespace
} else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
- type = AddImport(imports, union_enum, *ev.union_type.struct_def);
+ type = AddImport(imports, union_enum, *ev.union_type.struct_def).name;
} else {
FLATBUFFERS_ASSERT(false);
}
@@ -615,156 +635,140 @@
return ret;
}
- std::string AddImport(import_set &imports, const Definition &dependent,
- const StructDef &dependency) {
- std::string ns;
- const auto &depc_comps = dependency.defined_namespace->components;
- for (auto it = depc_comps.begin(); it != depc_comps.end(); it++) {
- ns += *it;
- }
- std::string unique_name = ns + dependency.name;
- std::string import_name = dependency.name;
- std::string long_import_name;
- if (imports.find(unique_name) != imports.end())
- return imports.find(unique_name)->second.name;
+ static bool CheckIfNameClashes(const import_set &imports,
+ const std::string &name) {
+ // TODO: this would be better as a hashset.
for (auto it = imports.begin(); it != imports.end(); it++) {
- if (it->second.name == import_name) {
- long_import_name = ns + import_name;
- break;
- }
+ if (it->second.name == name) { return true; }
}
-
- if (parser_.opts.ts_flat_file) {
- std::string file = dependency.declaration_file == nullptr
- ? dependency.file
- : dependency.declaration_file->substr(2);
- file = RelativeToRootPath(StripFileName(AbsolutePath(dependent.file)),
- dependency.file).substr(2);
- long_import_name = ns + import_name;
- flat_file_import_declarations_[file][import_name] = long_import_name;
- if (parser_.opts.generate_object_based_api) {
- flat_file_import_declarations_[file][import_name + "T"] = long_import_name + "T";
- }
- }
-
- std::string import_statement;
- std::string export_statement;
- import_statement += "import { ";
- export_statement += "export { ";
- std::string symbols_expression;
- if (long_import_name.empty()) {
- symbols_expression += EscapeKeyword(import_name);
- if (parser_.opts.generate_object_based_api)
- symbols_expression += ", " + import_name + "T";
- } else {
- symbols_expression += EscapeKeyword(dependency.name) + " as " +
- EscapeKeyword(long_import_name);
- if (parser_.opts.generate_object_based_api)
- symbols_expression +=
- ", " + dependency.name + "T as " + long_import_name + "T";
- }
- import_statement += symbols_expression + " } from '";
- export_statement += symbols_expression + " } from '";
- std::string bare_file_path;
- std::string rel_file_path;
- const auto &dep_comps = dependent.defined_namespace->components;
- for (size_t i = 0; i < dep_comps.size(); i++)
- rel_file_path += i == 0 ? ".." : (kPathSeparator + std::string(".."));
- if (dep_comps.size() == 0) rel_file_path += ".";
- for (auto it = depc_comps.begin(); it != depc_comps.end(); it++)
- bare_file_path +=
- kPathSeparator + ConvertCase(*it, Case::kDasher, Case::kUpperCamel);
- bare_file_path +=
- kPathSeparator +
- ConvertCase(dependency.name, Case::kDasher, Case::kUpperCamel);
- rel_file_path += bare_file_path;
- import_statement += rel_file_path + "';";
- export_statement += "." + bare_file_path + "';";
- ImportDefinition import;
- import.name = long_import_name.empty() ? import_name : long_import_name;
- import.bare_file_path = bare_file_path;
- import.rel_file_path = rel_file_path;
- import.import_statement = import_statement;
- import.export_statement = export_statement;
- import.dependency = &dependency;
- import.dependent = &dependent;
- imports.insert(std::make_pair(unique_name, import));
- return import.name;
+ return false;
}
- // TODO: largely (but not identical) duplicated code from above couln't find a
- // good way to refactor
- std::string AddImport(import_set &imports, const Definition &dependent,
- const EnumDef &dependency) {
- std::string ns;
- const auto &depc_comps = dependency.defined_namespace->components;
- for (auto it = depc_comps.begin(); it != depc_comps.end(); it++) {
- ns += *it;
- }
- std::string unique_name = ns + dependency.name;
- std::string import_name = EscapeKeyword(dependency.name);
- std::string long_import_name;
- if (imports.find(unique_name) != imports.end()) {
- return imports.find(unique_name)->second.name;
- }
- for (auto it = imports.begin(); it != imports.end(); it++) {
- if (it->second.name == import_name) {
- long_import_name = ns + import_name;
- break;
+ std::string GenSymbolExpression(const StructDef &struct_def,
+ const bool has_name_clash,
+ const std::string &import_name,
+ const std::string &name,
+ const std::string &object_name) {
+ std::string symbols_expression;
+
+ if (has_name_clash) {
+ // We have a name clash
+ symbols_expression += import_name + " as " + name;
+
+ if (parser_.opts.generate_object_based_api) {
+ symbols_expression += ", " +
+ GetTypeName(struct_def, /*object_api =*/true) +
+ " as " + object_name;
+ }
+ } else {
+ // No name clash, use the provided name
+ symbols_expression += name;
+
+ if (parser_.opts.generate_object_based_api) {
+ symbols_expression += ", " + object_name;
}
}
- if (parser_.opts.ts_flat_file) {
- std::string file = dependency.declaration_file == nullptr
- ? dependency.file
- : dependency.declaration_file->substr(2);
- file = RelativeToRootPath(StripFileName(AbsolutePath(dependent.file)),
- dependency.file).substr(2);
- long_import_name = ns + import_name;
- flat_file_import_declarations_[file][import_name] = long_import_name;
+ return symbols_expression;
+ }
+
+ std::string GenSymbolExpression(const EnumDef &enum_def,
+ const bool has_name_clash,
+ const std::string &import_name,
+ const std::string &name,
+ const std::string &) {
+ std::string symbols_expression;
+ if (has_name_clash) {
+ symbols_expression += import_name + " as " + name;
+ } else {
+ symbols_expression += name;
}
- std::string import_statement;
- std::string export_statement;
- import_statement += "import { ";
- export_statement += "export { ";
- std::string symbols_expression;
- if (long_import_name.empty())
- symbols_expression += import_name;
- else
- symbols_expression += EscapeKeyword(dependency.name) + " as " +
- EscapeKeyword(long_import_name);
- if (dependency.is_union) {
- symbols_expression += ", unionTo" + import_name;
- symbols_expression += ", unionListTo" + import_name;
+ if (enum_def.is_union) {
+ symbols_expression += ", unionTo" + name;
+ symbols_expression += ", unionListTo" + name;
}
- import_statement += symbols_expression + " } from '";
- export_statement += symbols_expression + " } from '";
+
+ return symbols_expression;
+ }
+
+ template<typename DefinitionT>
+ ImportDefinition AddImport(import_set &imports, const Definition &dependent,
+ const DefinitionT &dependency) {
+ // The unique name of the dependency, fully qualified in its namespace.
+ const std::string unique_name = GetTypeName(
+ dependency, /*object_api = */ false, /*force_ns_wrap=*/true);
+
+ // Look if we have already added this import and return its name if found.
+ const auto import_pair = imports.find(unique_name);
+ if (import_pair != imports.end()) { return import_pair->second; }
+
+ // Check if this name would have a name clash with another type. Just use
+ // the "base" name (properly escaped) without any namespacing applied.
+ const std::string import_name = GetTypeName(dependency);
+ const bool has_name_clash = CheckIfNameClashes(imports, import_name);
+
+ // If we have a name clash, use the unique name, otherwise use simple name.
+ std::string name = has_name_clash ? unique_name : import_name;
+
+ const std::string object_name =
+ GetTypeName(dependency, /*object_api=*/true, has_name_clash);
+
+ if (parser_.opts.ts_flat_file) {
+ // In flat-file generation, do not attempt to import things from ourselves
+ // *and* do not wrap namespaces (note that this does override the logic
+ // above, but since we force all non-self-imports to use namespace-based
+ // names in flat file generation, it's fine).
+ if (dependent.file == dependency.file) {
+ name = import_name;
+ } else {
+ const std::string file =
+ RelativeToRootPath(StripFileName(AbsolutePath(dependent.file)),
+ dependency.file)
+ // Strip the leading //
+ .substr(2);
+ flat_file_import_declarations_[file][import_name] = name;
+
+ if (parser_.opts.generate_object_based_api &&
+ SupportsObjectAPI<DefinitionT>::value) {
+ flat_file_import_declarations_[file][import_name + "T"] = object_name;
+ }
+ }
+ }
+
+ const std::string symbols_expression = GenSymbolExpression(
+ dependency, has_name_clash, import_name, name, object_name);
+
std::string bare_file_path;
std::string rel_file_path;
const auto &dep_comps = dependent.defined_namespace->components;
- for (size_t i = 0; i < dep_comps.size(); i++)
+ for (size_t i = 0; i < dep_comps.size(); i++) {
rel_file_path += i == 0 ? ".." : (kPathSeparator + std::string(".."));
- if (dep_comps.size() == 0) rel_file_path += ".";
- for (auto it = depc_comps.begin(); it != depc_comps.end(); it++)
- bare_file_path +=
- kPathSeparator + ConvertCase(*it, Case::kDasher, Case::kUpperCamel);
+ }
+ if (dep_comps.size() == 0) { rel_file_path += "."; }
+
bare_file_path +=
kPathSeparator +
- ConvertCase(dependency.name, Case::kDasher, Case::kUpperCamel);
+ namer_.Directories(dependency.defined_namespace->components,
+ SkipDir::OutputPath) +
+ namer_.File(dependency, SkipFile::SuffixAndExtension);
rel_file_path += bare_file_path;
- import_statement += rel_file_path + "';";
- export_statement += "." + bare_file_path + "';";
+
ImportDefinition import;
- import.name = long_import_name.empty() ? import_name : long_import_name;
+ import.name = name;
+ import.object_name = object_name;
import.bare_file_path = bare_file_path;
import.rel_file_path = rel_file_path;
- import.import_statement = import_statement;
- import.export_statement = export_statement;
+ import.import_statement =
+ "import { " + symbols_expression + " } from '" + rel_file_path + ".js';";
+ import.export_statement =
+ "export { " + symbols_expression + " } from '." + bare_file_path + ".js';";
import.dependency = &dependency;
import.dependent = &dependent;
+
imports.insert(std::make_pair(unique_name, import));
- return import.name;
+
+ return import;
}
void AddImport(import_set &imports, std::string import_name,
@@ -777,7 +781,9 @@
}
// Generate a TS union type based on a union's enum
- std::string GenObjApiUnionTypeTS(import_set &imports, const IDLOptions &opts,
+ std::string GenObjApiUnionTypeTS(import_set &imports,
+ const StructDef &dependent,
+ const IDLOptions &,
const EnumDef &union_enum) {
std::string ret = "";
std::set<std::string> type_list;
@@ -791,8 +797,8 @@
if (IsString(ev.union_type)) {
type = "string"; // no need to wrap string type in namespace
} else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
- type = GetObjApiClassName(
- AddImport(imports, union_enum, *ev.union_type.struct_def), opts);
+ type = AddImport(imports, dependent, *ev.union_type.struct_def)
+ .object_name;
} else {
FLATBUFFERS_ASSERT(false);
}
@@ -809,11 +815,11 @@
}
std::string GenUnionConvFuncName(const EnumDef &enum_def) {
- return "unionTo" + enum_def.name;
+ return namer_.Function("unionTo", enum_def);
}
std::string GenUnionListConvFuncName(const EnumDef &enum_def) {
- return "unionListTo" + enum_def.name;
+ return namer_.Function("unionListTo", enum_def);
}
std::string GenUnionConvFunc(const Type &union_type, import_set &imports) {
@@ -824,12 +830,12 @@
const auto valid_union_type_with_null = valid_union_type + "|null";
auto ret = "\n\nexport function " + GenUnionConvFuncName(enum_def) +
- "(\n type: " + enum_def.name +
+ "(\n type: " + GetTypeName(enum_def) +
",\n accessor: (obj:" + valid_union_type + ") => " +
valid_union_type_with_null +
"\n): " + valid_union_type_with_null + " {\n";
- const auto enum_type = AddImport(imports, enum_def, enum_def);
+ const auto enum_type = AddImport(imports, enum_def, enum_def).name;
const auto union_enum_loop = [&](const std::string &accessor_str) {
ret += " switch(" + enum_type + "[type]) {\n";
@@ -840,13 +846,13 @@
const auto &ev = **it;
if (ev.IsZero()) { continue; }
- ret += " case '" + ev.name + "': ";
+ ret += " case '" + namer_.Variant(ev) + "': ";
if (IsString(ev.union_type)) {
ret += "return " + accessor_str + "'') as string;";
} else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
const auto type =
- AddImport(imports, enum_def, *ev.union_type.struct_def);
+ AddImport(imports, enum_def, *ev.union_type.struct_def).name;
ret += "return " + accessor_str + "new " + type + "())! as " +
type + ";";
} else {
@@ -863,7 +869,7 @@
ret += "}";
ret += "\n\nexport function " + GenUnionListConvFuncName(enum_def) +
- "(\n type: " + enum_def.name +
+ "(\n type: " + GetTypeName(enum_def) +
", \n accessor: (index: number, obj:" + valid_union_type +
") => " + valid_union_type_with_null +
", \n index: number\n): " + valid_union_type_with_null + " {\n";
@@ -879,12 +885,13 @@
// Used for generating a short function that returns the correct class
// based on union enum type. Assume the context is inside the non object api
// type
- std::string GenUnionValTS(import_set &imports, const std::string &field_name,
+ std::string GenUnionValTS(import_set &imports, const StructDef &dependent,
+ const std::string &field_name,
const Type &union_type,
const bool is_array = false) {
if (union_type.enum_def) {
const auto &enum_def = *union_type.enum_def;
- const auto enum_type = AddImport(imports, enum_def, enum_def);
+ const auto enum_type = AddImport(imports, dependent, enum_def).name;
const std::string union_accessor = "this." + field_name;
const auto union_has_string = UnionHasStringType(enum_def);
@@ -894,11 +901,11 @@
if (!is_array) {
const auto conversion_function = GenUnionConvFuncName(enum_def);
- const auto target_enum = "this." + field_name + "Type()";
ret = "(() => {\n";
- ret += " let temp = " + conversion_function + "(" + target_enum +
- ", " + field_binded_method + ");\n";
+ ret += " let temp = " + conversion_function + "(this." +
+ namer_.Method(field_name, "Type") + "(), " +
+ field_binded_method + ");\n";
ret += " if(temp === null) { return null; }\n";
ret += union_has_string
? " if(typeof temp === 'string') { return temp; }\n"
@@ -907,17 +914,15 @@
ret += " })()";
} else {
const auto conversion_function = GenUnionListConvFuncName(enum_def);
- const auto target_enum_accesor = "this." + field_name + "Type";
- const auto target_enum_length = target_enum_accesor + "Length()";
ret = "(() => {\n";
ret += " let ret = [];\n";
- ret += " for(let targetEnumIndex = 0; targetEnumIndex < " +
- target_enum_length +
+ ret += " for(let targetEnumIndex = 0; targetEnumIndex < this." +
+ namer_.Method(field_name, "TypeLength") + "()" +
"; "
"++targetEnumIndex) {\n";
- ret += " let targetEnum = " + target_enum_accesor +
- "(targetEnumIndex);\n";
+ ret += " let targetEnum = this." +
+ namer_.Method(field_name, "Type") + "(targetEnumIndex);\n";
ret += " if(targetEnum === null || " + enum_type +
"[targetEnum!] === 'NONE') { "
"continue; }\n\n";
@@ -956,15 +961,20 @@
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
- const auto curr_member_accessor =
- prefix + "." + ConvertCase(field.name, Case::kLowerCamel);
+ auto curr_member_accessor = prefix + "." + namer_.Method(field);
+ if (prefix != "this") {
+ curr_member_accessor = prefix + "?." + namer_.Method(field);
+ }
if (IsStruct(field.value.type)) {
ret += GenStructMemberValueTS(*field.value.type.struct_def,
curr_member_accessor, delimiter);
} else {
if (nullCheck) {
- ret +=
- "(" + prefix + " === null ? 0 : " + curr_member_accessor + "!)";
+ std::string nullValue = "0";
+ if (field.value.type.base_type == BASE_TYPE_BOOL) {
+ nullValue = "false";
+ }
+ ret += "(" + curr_member_accessor + " ?? " + nullValue + ")";
} else {
ret += curr_member_accessor;
}
@@ -979,7 +989,7 @@
void GenObjApi(const Parser &parser, StructDef &struct_def,
std::string &obj_api_unpack_func, std::string &obj_api_class,
import_set &imports) {
- const auto class_name = GetObjApiClassName(struct_def, parser.opts);
+ const auto class_name = GetTypeName(struct_def, /*object_api=*/true);
std::string unpack_func = "\nunpack(): " + class_name +
" {\n return new " + class_name + "(" +
@@ -999,8 +1009,7 @@
std::string pack_func_offset_decl;
std::string pack_func_create_call;
- const auto struct_name =
- EscapeKeyword(AddImport(imports, struct_def, struct_def));
+ const auto struct_name = AddImport(imports, struct_def, struct_def).name;
if (has_create) {
pack_func_create_call = " return " + struct_name + ".create" +
@@ -1023,10 +1032,10 @@
auto &field = **it;
if (field.deprecated) continue;
- const auto field_name = ConvertCase(field.name, Case::kLowerCamel);
- const auto field_name_escaped = EscapeKeyword(field_name);
+ const auto field_method = namer_.Method(field);
+ const auto field_field = namer_.Field(field);
const std::string field_binded_method =
- "this." + field_name + ".bind(this)";
+ "this." + field_method + ".bind(this)";
std::string field_val;
std::string field_type;
@@ -1046,14 +1055,14 @@
field_type += GenTypeName(imports, field, field.value.type, false,
has_null_default);
- field_val = "this." + field_name + "()";
+ field_val = "this." + namer_.Method(field) + "()";
if (field.value.type.base_type != BASE_TYPE_STRING) {
- field_offset_val = "this." + field_name_escaped;
+ field_offset_val = "this." + namer_.Field(field);
} else {
field_offset_decl = GenNullCheckConditional(
- "this." + field_name_escaped,
- "builder.createString(this." + field_name_escaped + "!)", "0");
+ "this." + namer_.Field(field),
+ "builder.createString(this." + field_field + "!)", "0");
}
}
@@ -1063,17 +1072,15 @@
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
const auto &sd = *field.value.type.struct_def;
- field_type += GetObjApiClassName(AddImport(imports, struct_def, sd),
- parser.opts);
+ field_type += AddImport(imports, struct_def, sd).object_name;
const std::string field_accessor =
- "this." + field_name_escaped + "()";
+ "this." + namer_.Method(field) + "()";
field_val = GenNullCheckConditional(field_accessor,
field_accessor + "!.unpack()");
auto packing = GenNullCheckConditional(
- "this." + field_name_escaped,
- "this." + field_name_escaped + "!.pack(builder)",
- "0");
+ "this." + field_field,
+ "this." + field_field + "!.pack(builder)", "0");
if (sd.fixed) {
field_offset_val = std::move(packing);
@@ -1095,29 +1102,25 @@
switch (vectortype.base_type) {
case BASE_TYPE_STRUCT: {
const auto &sd = *field.value.type.struct_def;
- field_type += GetObjApiClassName(
- AddImport(imports, struct_def, sd), parser.opts);
+ field_type += GetTypeName(sd, /*object_api=*/true);
+ ;
field_type += ")[]";
field_val = GenBBAccess() + ".createObjList(" +
- field_binded_method + ", this." + field_name +
- "Length())";
+ field_binded_method + ", this." +
+ namer_.Method(field, "Length") + "())";
if (sd.fixed) {
field_offset_decl =
- "builder.createStructOffsetList(this." +
- field_name_escaped + ", " +
- EscapeKeyword(
- AddImport(imports, struct_def, struct_def)) +
- ".start" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector)";
+ "builder.createStructOffsetList(this." + field_field +
+ ", " + AddImport(imports, struct_def, struct_def).name +
+ "." + namer_.Method("start", field, "Vector") + ")";
} else {
field_offset_decl =
- EscapeKeyword(
- AddImport(imports, struct_def, struct_def)) +
- ".create" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector(builder, builder.createObjectOffsetList(" +
- "this." + field_name_escaped + "))";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ field_field + "))";
}
break;
@@ -1126,28 +1129,28 @@
case BASE_TYPE_STRING: {
field_type += "string)[]";
field_val = GenBBAccess() + ".createScalarList(" +
- field_binded_method + ", this." + field_name +
- "Length())";
+ field_binded_method + ", this." +
+ namer_.Field(field, "Length") + "())";
field_offset_decl =
- EscapeKeyword(AddImport(imports, struct_def, struct_def)) +
- ".create" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector(builder, builder.createObjectOffsetList(" +
- "this." + field_name_escaped + "))";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
break;
}
case BASE_TYPE_UNION: {
- field_type += GenObjApiUnionTypeTS(imports, parser.opts,
- *(vectortype.enum_def));
+ field_type += GenObjApiUnionTypeTS(
+ imports, struct_def, parser.opts, *(vectortype.enum_def));
field_type += ")[]";
- field_val =
- GenUnionValTS(imports, field_name, vectortype, true);
+ field_val = GenUnionValTS(imports, struct_def, field_method,
+ vectortype, true);
field_offset_decl =
- EscapeKeyword(AddImport(imports, struct_def, struct_def)) +
- ".create" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector(builder, builder.createObjectOffsetList(" +
- "this." + field_name_escaped + "))";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
break;
}
@@ -1160,13 +1163,13 @@
}
field_type += ")[]";
field_val = GenBBAccess() + ".createScalarList(" +
- field_binded_method + ", this." + field_name +
- "Length())";
+ field_binded_method + ", this." +
+ namer_.Method(field, "Length") + "())";
field_offset_decl =
- EscapeKeyword(AddImport(imports, struct_def, struct_def)) +
- ".create" + ConvertCase(field_name, Case::kUpperCamel) +
- "Vector(builder, this." + field_name_escaped + ")";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, this." + field_field + ")";
break;
}
@@ -1176,12 +1179,13 @@
}
case BASE_TYPE_UNION: {
- field_type += GenObjApiUnionTypeTS(imports, parser.opts,
+ field_type += GenObjApiUnionTypeTS(imports, struct_def, parser.opts,
*(field.value.type.enum_def));
- field_val = GenUnionValTS(imports, field_name, field.value.type);
+ field_val = GenUnionValTS(imports, struct_def, field_method,
+ field.value.type);
field_offset_decl =
- "builder.createObjectOffset(this." + field_name_escaped + ")";
+ "builder.createObjectOffset(this." + field_field + ")";
break;
}
@@ -1194,18 +1198,17 @@
if (!field_offset_decl.empty()) {
field_offset_decl =
- " const " + field_name_escaped + " = " + field_offset_decl + ";";
+ " const " + field_field + " = " + field_offset_decl + ";";
}
- if (field_offset_val.empty()) { field_offset_val = field_name_escaped; }
+ if (field_offset_val.empty()) { field_offset_val = field_field; }
unpack_func += " " + field_val;
- unpack_to_func += " _o." + field_name_escaped + " = " + field_val + ";";
+ unpack_to_func += " _o." + field_field + " = " + field_val + ";";
- // FIXME: if field_type and field_name_escaped are identical, then
+ // FIXME: if field_type and field_field are identical, then
// this generates invalid typescript.
- constructor_func += " public " + field_name_escaped + ": " + field_type +
- " = " +
- field_default_val;
+ constructor_func += " public " + field_field + ": " + field_type +
+ " = " + field_default_val;
if (!struct_def.fixed) {
if (!field_offset_decl.empty()) {
@@ -1216,11 +1219,12 @@
pack_func_create_call += field_offset_val;
} else {
if (field.IsScalarOptional()) {
- pack_func_create_call += " if (" + field_offset_val + " !== null)\n ";
+ pack_func_create_call +=
+ " if (" + field_offset_val + " !== null)\n ";
}
- pack_func_create_call += " " + struct_name + ".add" +
- ConvertCase(field.name, Case::kUpperCamel) +
- "(builder, " + field_offset_val + ");\n";
+ pack_func_create_call += " " + struct_name + "." +
+ namer_.Method("add", field) + "(builder, " +
+ field_offset_val + ");\n";
}
}
@@ -1253,10 +1257,10 @@
pack_func_create_call += "return " + struct_name + ".end" +
GetPrefixedName(struct_def) + "(builder);";
}
-
- obj_api_class = "\nexport class " +
- GetObjApiClassName(struct_def, parser.opts) + " {\n";
-
+ obj_api_class = "\n";
+ obj_api_class += "export class ";
+ obj_api_class += GetTypeName(struct_def, /*object_api=*/true);
+ obj_api_class += " {\n";
obj_api_class += constructor_func;
obj_api_class += pack_func_prototype + pack_func_offset_decl +
pack_func_create_call + "\n}";
@@ -1287,13 +1291,18 @@
if (struct_def.generated) return;
std::string &code = *code_ptr;
- std::string object_name;
- std::string object_namespace = GetNameSpace(struct_def);
+ // Special case for the root struct, since no one will necessarily reference
+ // it, we have to explicitly add it to the import list.
+ if (&struct_def == parser_.root_struct_def_) {
+ AddImport(imports, struct_def, struct_def);
+ }
+
+ const std::string object_name = GetTypeName(struct_def);
// Emit constructor
- object_name = EscapeKeyword(struct_def.name);
GenDocComment(struct_def.doc_comment, code_ptr);
- code += "export class " + object_name;
+ code += "export class ";
+ code += object_name;
code += " {\n";
code += " bb: flatbuffers.ByteBuffer|null = null;\n";
code += " bb_pos = 0;\n";
@@ -1301,7 +1310,7 @@
// Generate the __init method that sets the field in a pre-existing
// accessor object. This is to allow object reuse.
code +=
- "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + " {\n";
+ " __init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + " {\n";
code += " this.bb_pos = i;\n";
code += " this.bb = bb;\n";
code += " return this;\n";
@@ -1338,7 +1347,7 @@
const auto has_null_default = is_string || HasNullDefault(field);
GenDocComment(field.doc_comment, code_ptr);
- std::string prefix = ConvertCase(field.name, Case::kLowerCamel) + "(";
+ std::string prefix = namer_.Method(field) + "(";
if (is_string) {
code += prefix + "):string|null\n";
code +=
@@ -1381,10 +1390,11 @@
else {
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
- const auto type = EscapeKeyword(
- AddImport(imports, struct_def, *field.value.type.struct_def));
+ const auto type =
+ AddImport(imports, struct_def, *field.value.type.struct_def)
+ .name;
GenDocComment(field.doc_comment, code_ptr);
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += namer_.Method(field);
code += "(obj?:" + type + "):" + type + "|null {\n";
if (struct_def.fixed) {
@@ -1424,7 +1434,7 @@
default: ret_type = vectortypename;
}
GenDocComment(field.doc_comment, code_ptr);
- std::string prefix = ConvertCase(field.name, Case::kLowerCamel);
+ std::string prefix = namer_.Method(field);
// TODO: make it work without any
// if (is_union) { prefix += "<T extends flatbuffers.Table>"; }
if (is_union) { prefix += ""; }
@@ -1484,7 +1494,7 @@
case BASE_TYPE_UNION: {
GenDocComment(field.doc_comment, code_ptr);
- code += ConvertCase(field.name, Case::kLowerCamel);
+ code += namer_.Method(field);
const auto &union_enum = *(field.value.type.enum_def);
const auto union_type = GenUnionGenericTypeTS(union_enum);
@@ -1509,12 +1519,15 @@
std::string type =
GenTypeName(imports, struct_def, field.value.type, true);
- code += "mutate_" + field.name + "(value:" + type + "):boolean {\n";
+ code += namer_.LegacyTsMutateMethod(field) + "(value:" + type +
+ "):boolean {\n";
+
+ const std::string write_method =
+ "." + namer_.Method("write", GenType(field.value.type));
if (struct_def.fixed) {
- code += " " + GenBBAccess() + ".write" +
- ConvertCase(GenType(field.value.type), Case::kUpperCamel) +
- "(this.bb_pos + " + NumToString(field.value.offset) + ", ";
+ code += " " + GenBBAccess() + write_method + "(this.bb_pos + " +
+ NumToString(field.value.offset) + ", ";
} else {
code += " const offset = " + GenBBAccess() +
".__offset(this.bb_pos, " + NumToString(field.value.offset) +
@@ -1524,9 +1537,8 @@
code += " }\n\n";
// special case for bools, which are treated as uint8
- code += " " + GenBBAccess() + ".write" +
- ConvertCase(GenType(field.value.type), Case::kUpperCamel) +
- "(this.bb_pos + offset, ";
+ code +=
+ " " + GenBBAccess() + write_method + "(this.bb_pos + offset, ";
if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; }
}
@@ -1539,8 +1551,8 @@
if (IsVector(field.value.type)) {
// Emit a length helper
GenDocComment(code_ptr);
- code += ConvertCase(field.name, Case::kLowerCamel);
- code += "Length():number {\n" + offset_prefix;
+ code += namer_.Method(field, "Length");
+ code += "():number {\n" + offset_prefix;
code +=
GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n}\n\n";
@@ -1550,9 +1562,9 @@
if (IsScalar(vectorType.base_type) && !IsLong(vectorType.base_type)) {
GenDocComment(code_ptr);
- code += ConvertCase(field.name, Case::kLowerCamel);
- code += "Array():" + GenType(vectorType) + "Array|null {\n" +
- offset_prefix;
+ code += namer_.Method(field, "Array");
+ code +=
+ "():" + GenType(vectorType) + "Array|null {\n" + offset_prefix;
code += "new " + GenType(vectorType) + "Array(" + GenBBAccess() +
".bytes().buffer, " + GenBBAccess() +
@@ -1611,7 +1623,7 @@
// Generate the field insertion method
GenDocComment(code_ptr);
- code += "static add" + ConvertCase(field.name, Case::kUpperCamel);
+ code += "static " + namer_.Method("add", field);
code += "(builder:flatbuffers.Builder, " + argname + ":" +
GetArgType(imports, struct_def, field, false) + ") {\n";
code += " builder.addField" + GenWriteMethod(field.value.type) + "(";
@@ -1642,8 +1654,8 @@
GenDocComment(code_ptr);
const std::string sig_begin =
- "static create" + ConvertCase(field.name, Case::kUpperCamel) +
- "Vector(builder:flatbuffers.Builder, data:";
+ "static " + namer_.Method("create", field, "Vector") +
+ "(builder:flatbuffers.Builder, data:";
const std::string sig_end = "):flatbuffers.Offset";
std::string type =
GenTypeName(imports, struct_def, vector_type, true) + "[]";
@@ -1680,8 +1692,9 @@
// after
GenDocComment(code_ptr);
- code += "static start" + ConvertCase(field.name, Case::kUpperCamel);
- code += "Vector(builder:flatbuffers.Builder, numElems:number) {\n";
+ code += "static ";
+ code += namer_.Method("start", field, "Vector");
+ code += "(builder:flatbuffers.Builder, numElems:number) {\n";
code += " builder.startVector(" + NumToString(elem_size);
code += ", numElems, " + NumToString(alignment) + ");\n";
code += "}\n\n";
@@ -1724,8 +1737,8 @@
}
code += "):flatbuffers.Offset {\n";
- code += " " + object_name + ".start" +
- GetPrefixedName(struct_def) + "(builder);\n";
+ code += " " + object_name + ".start" + GetPrefixedName(struct_def) +
+ "(builder);\n";
std::string methodPrefix = object_name;
for (auto it = struct_def.fields.vec.begin();
@@ -1739,8 +1752,7 @@
code += " if (" + arg_name + " !== null)\n ";
}
- code += " " + methodPrefix + ".add" +
- ConvertCase(field.name, Case::kUpperCamel) + "(";
+ code += " " + methodPrefix + "." + namer_.Method("add", field) + "(";
code += "builder, " + arg_name + ");\n";
}
@@ -1758,10 +1770,9 @@
code += "}\n";
code += "\n";
- code += "static deserialize(buffer: Uint8Array):" + EscapeKeyword(name) +
- " {\n";
- code += " return " +
- EscapeKeyword(AddImport(imports, struct_def, struct_def)) +
+ code += "static deserialize(buffer: Uint8Array):" +
+ namer_.EscapeKeyword(name) + " {\n";
+ code += " return " + AddImport(imports, struct_def, struct_def).name +
".getRootAs" + name + "(new flatbuffers.ByteBuffer(buffer))\n";
code += "}\n";
}
@@ -1789,12 +1800,8 @@
}
std::string GetArgName(const FieldDef &field) {
- auto argname = ConvertCase(field.name, Case::kLowerCamel);
- if (!IsScalar(field.value.type.base_type)) {
- argname += "Offset";
- } else {
- argname = EscapeKeyword(argname);
- }
+ auto argname = namer_.Variable(field);
+ if (!IsScalar(field.value.type.base_type)) { argname += "Offset"; }
return argname;
}
diff --git a/third_party/flatbuffers/src/idl_namer.h b/third_party/flatbuffers/src/idl_namer.h
new file mode 100644
index 0000000..f60e30c
--- /dev/null
+++ b/third_party/flatbuffers/src/idl_namer.h
@@ -0,0 +1,168 @@
+#ifndef FLATBUFFERS_IDL_NAMER
+#define FLATBUFFERS_IDL_NAMER
+
+#include "flatbuffers/idl.h"
+#include "namer.h"
+
+namespace flatbuffers {
+
+// Provides Namer capabilities to types defined in the flatbuffers IDL.
+class IdlNamer : public Namer {
+ public:
+ explicit IdlNamer(Config config, std::set<std::string> keywords)
+ : Namer(config, std::move(keywords)) {}
+
+ using Namer::Constant;
+ using Namer::Directories;
+ using Namer::Field;
+ using Namer::File;
+ using Namer::Function;
+ using Namer::Method;
+ using Namer::Namespace;
+ using Namer::NamespacedType;
+ using Namer::ObjectType;
+ using Namer::Type;
+ using Namer::Variable;
+ using Namer::Variant;
+
+ std::string Constant(const FieldDef &d) const { return Constant(d.name); }
+
+ // Types are always structs or enums so we can only expose these two
+ // overloads.
+ std::string Type(const StructDef &d) const { return Type(d.name); }
+ std::string Type(const EnumDef &d) const { return Type(d.name); }
+
+ std::string Function(const Definition &s) const { return Function(s.name); }
+ std::string Function(const std::string& prefix, const Definition &s) const {
+ return Function(prefix + s.name);
+ }
+
+ std::string Field(const FieldDef &s) const { return Field(s.name); }
+ std::string Field(const FieldDef &d, const std::string &s) const {
+ return Field(d.name + "_" + s);
+ }
+
+ std::string Variable(const FieldDef &s) const { return Variable(s.name); }
+
+ std::string Variable(const StructDef &s) const { return Variable(s.name); }
+
+ std::string Variant(const EnumVal &s) const { return Variant(s.name); }
+
+ std::string EnumVariant(const EnumDef &e, const EnumVal &v) const {
+ return Type(e) + config_.enum_variant_seperator + Variant(v);
+ }
+
+ std::string ObjectType(const StructDef &d) const {
+ return ObjectType(d.name);
+ }
+ std::string ObjectType(const EnumDef &d) const { return ObjectType(d.name); }
+
+ std::string Method(const FieldDef &d, const std::string &suffix) const {
+ return Method(d.name, suffix);
+ }
+ std::string Method(const std::string &prefix, const StructDef &d) const {
+ return Method(prefix, d.name);
+ }
+ std::string Method(const std::string &prefix, const FieldDef &d) const {
+ return Method(prefix, d.name);
+ }
+ std::string Method(const std::string &prefix, const FieldDef &d,
+ const std::string &suffix) const {
+ return Method(prefix, d.name, suffix);
+ }
+
+ std::string Namespace(const struct Namespace &ns) const {
+ return Namespace(ns.components);
+ }
+
+ std::string NamespacedEnumVariant(const EnumDef &e, const EnumVal &v) const {
+ return NamespacedString(e.defined_namespace, EnumVariant(e, v));
+ }
+
+ std::string NamespacedType(const Definition &def) const {
+ return NamespacedString(def.defined_namespace, Type(def.name));
+ }
+
+ std::string NamespacedObjectType(const Definition &def) const {
+ return NamespacedString(def.defined_namespace, ObjectType(def.name));
+ }
+
+ std::string Directories(const struct Namespace &ns,
+ SkipDir skips = SkipDir::None) const {
+ return Directories(ns.components, skips);
+ }
+
+ // Legacy fields do not really follow the usual config and should be
+ // considered for deprecation.
+
+ std::string LegacyRustNativeVariant(const EnumVal &v) const {
+ return ConvertCase(EscapeKeyword(v.name), Case::kUpperCamel);
+ }
+
+ std::string LegacyRustFieldOffsetName(const FieldDef &field) const {
+ return "VT_" + ConvertCase(EscapeKeyword(field.name), Case::kAllUpper);
+ }
+
+ std::string LegacySwiftVariant(const EnumVal &ev) const {
+ auto name = ev.name;
+ if (isupper(name.front())) {
+ std::transform(name.begin(), name.end(), name.begin(), CharToLower);
+ }
+ return EscapeKeyword(ConvertCase(name, Case::kLowerCamel));
+ }
+
+ // Also used by Kotlin, lol.
+ std::string LegacyJavaMethod2(const std::string &prefix, const StructDef &sd,
+ const std::string &suffix) const {
+ return prefix + sd.name + suffix;
+ }
+
+ std::string LegacyKotlinVariant(EnumVal &ev) const {
+ // Namer assumes the input case is snake case which is wrong...
+ return ConvertCase(EscapeKeyword(ev.name), Case::kLowerCamel);
+ }
+ // Kotlin methods escapes keywords after case conversion but before
+ // prefixing and suffixing.
+ std::string LegacyKotlinMethod(const std::string &prefix, const FieldDef &d,
+ const std::string &suffix) const {
+ return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) +
+ suffix;
+ }
+ std::string LegacyKotlinMethod(const std::string &prefix, const StructDef &d,
+ const std::string &suffix) const {
+ return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) +
+ suffix;
+ }
+
+ // This is a mix of snake case and keep casing, when Ts should be using
+ // lower camel case.
+ std::string LegacyTsMutateMethod(const FieldDef& d) {
+ return "mutate_" + d.name;
+ }
+
+ private:
+ std::string NamespacedString(const struct Namespace *ns,
+ const std::string &str) const {
+ std::string ret;
+ if (ns != nullptr) { ret += Namespace(ns->components); }
+ if (!ret.empty()) ret += config_.namespace_seperator;
+ return ret + str;
+ }
+};
+
+// This is a temporary helper function for code generators to call until all
+// flag-overriding logic into flatc.cpp
+inline Namer::Config WithFlagOptions(const Namer::Config &input,
+ const IDLOptions &opts,
+ const std::string &path) {
+ Namer::Config result = input;
+ result.object_prefix = opts.object_prefix;
+ result.object_suffix = opts.object_suffix;
+ result.output_path = path;
+ result.filename_suffix = opts.filename_suffix;
+ return result;
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_NAMER
diff --git a/third_party/flatbuffers/src/idl_parser.cpp b/third_party/flatbuffers/src/idl_parser.cpp
index e9aa477..497e82b 100644
--- a/third_party/flatbuffers/src/idl_parser.cpp
+++ b/third_party/flatbuffers/src/idl_parser.cpp
@@ -36,24 +36,9 @@
// clang-format on
}
-const double kPi = 3.14159265358979323846;
+namespace {
-// clang-format off
-const char *const kTypeNames[] = {
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
- IDLTYPE,
- FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
- #undef FLATBUFFERS_TD
- nullptr
-};
-
-const char kTypeSizes[] = {
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
- sizeof(CTYPE),
- FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
- #undef FLATBUFFERS_TD
-};
-// clang-format on
+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.
@@ -93,97 +78,36 @@
return true;
}
-void DeserializeDoc(std::vector<std::string> &doc,
- const Vector<Offset<String>> *documentation) {
+static void DeserializeDoc(std::vector<std::string> &doc,
+ const Vector<Offset<String>> *documentation) {
if (documentation == nullptr) return;
for (uoffset_t index = 0; index < documentation->size(); index++)
doc.push_back(documentation->Get(index)->str());
}
-void Parser::Message(const std::string &msg) {
- if (!error_.empty()) error_ += "\n"; // log all warnings and errors
- error_ += file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : "";
- // clang-format off
+static CheckedError NoError() { return CheckedError(false); }
- #ifdef _WIN32 // MSVC alike
- error_ +=
- "(" + NumToString(line_) + ", " + NumToString(CursorPosition()) + ")";
- #else // gcc alike
- if (file_being_parsed_.length()) error_ += ":";
- error_ += NumToString(line_) + ": " + NumToString(CursorPosition());
- #endif
- // clang-format on
- error_ += ": " + msg;
-}
-
-void Parser::Warning(const std::string &msg) {
- if (!opts.no_warnings) {
- Message("warning: " + msg);
- has_warning_ = true; // for opts.warnings_as_errors
- }
-}
-
-CheckedError Parser::Error(const std::string &msg) {
- Message("error: " + msg);
- return CheckedError(true);
-}
-
-inline CheckedError NoError() { return CheckedError(false); }
-
-CheckedError Parser::RecurseError() {
- return Error("maximum parsing depth " + NumToString(parse_depth_counter_) +
- " reached");
-}
-
-const std::string &Parser::GetPooledString(const std::string &s) const {
- return *(string_cache_.insert(s).first);
-}
-
-class Parser::ParseDepthGuard {
- public:
- explicit ParseDepthGuard(Parser *parser_not_null)
- : parser_(*parser_not_null), caller_depth_(parser_.parse_depth_counter_) {
- FLATBUFFERS_ASSERT(caller_depth_ <= (FLATBUFFERS_MAX_PARSING_DEPTH) &&
- "Check() must be called to prevent stack overflow");
- parser_.parse_depth_counter_ += 1;
- }
-
- ~ParseDepthGuard() { parser_.parse_depth_counter_ -= 1; }
-
- CheckedError Check() {
- return caller_depth_ >= (FLATBUFFERS_MAX_PARSING_DEPTH)
- ? parser_.RecurseError()
- : CheckedError(false);
- }
-
- FLATBUFFERS_DELETE_FUNC(ParseDepthGuard(const ParseDepthGuard &));
- FLATBUFFERS_DELETE_FUNC(ParseDepthGuard &operator=(const ParseDepthGuard &));
-
- private:
- Parser &parser_;
- const int caller_depth_;
-};
-
-template<typename T> std::string TypeToIntervalString() {
+template<typename T> static std::string TypeToIntervalString() {
return "[" + NumToString((flatbuffers::numeric_limits<T>::lowest)()) + "; " +
NumToString((flatbuffers::numeric_limits<T>::max)()) + "]";
}
// atot: template version of atoi/atof: convert a string to an instance of T.
template<typename T>
-bool atot_scalar(const char *s, T *val, bool_constant<false>) {
+static bool atot_scalar(const char *s, T *val, bool_constant<false>) {
return StringToNumber(s, val);
}
template<typename T>
-bool atot_scalar(const char *s, T *val, bool_constant<true>) {
+static bool atot_scalar(const char *s, T *val, bool_constant<true>) {
// Normalize NaN parsed from fbs or json to unsigned NaN.
if (false == StringToNumber(s, val)) return false;
*val = (*val != *val) ? std::fabs(*val) : *val;
return true;
}
-template<typename T> CheckedError atot(const char *s, Parser &parser, T *val) {
+template<typename T>
+static CheckedError atot(const char *s, Parser &parser, T *val) {
auto done = atot_scalar(s, val, bool_constant<is_floating_point<T>::value>());
if (done) return NoError();
if (0 == *val)
@@ -193,33 +117,18 @@
", constant does not fit " + TypeToIntervalString<T>());
}
template<>
-inline CheckedError atot<Offset<void>>(const char *s, Parser &parser,
- Offset<void> *val) {
+CheckedError atot<Offset<void>>(const char *s, Parser &parser,
+ Offset<void> *val) {
(void)parser;
*val = Offset<void>(atoi(s));
return NoError();
}
-std::string Namespace::GetFullyQualifiedName(const std::string &name,
- size_t max_components) const {
- // Early exit if we don't have a defined namespace.
- if (components.empty() || !max_components) { return name; }
- std::string stream_str;
- for (size_t i = 0; i < std::min(components.size(), max_components); i++) {
- stream_str += components[i];
- stream_str += '.';
- }
- if (!stream_str.empty()) stream_str.pop_back();
- if (name.length()) {
- stream_str += '.';
- stream_str += name;
- }
- return stream_str;
-}
-
template<typename T>
-T *LookupTableByName(const SymbolTable<T> &table, const std::string &name,
- const Namespace ¤t_namespace, size_t skip_top) {
+static T *LookupTableByName(const SymbolTable<T> &table,
+ const std::string &name,
+ const Namespace ¤t_namespace,
+ size_t skip_top) {
const auto &components = current_namespace.components;
if (table.dict.empty()) return nullptr;
if (components.size() < skip_top) return nullptr;
@@ -278,6 +187,271 @@
}
// clang-format on
+static bool IsIdentifierStart(char c) { return is_alpha(c) || (c == '_'); }
+
+static bool CompareSerializedScalars(const uint8_t *a, const uint8_t *b,
+ const FieldDef &key) {
+ switch (key.value.type.base_type) {
+#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_##ENUM: { \
+ CTYPE def = static_cast<CTYPE>(0); \
+ if (!a || !b) { StringToNumber(key.value.constant.c_str(), &def); } \
+ const auto av = a ? ReadScalar<CTYPE>(a) : def; \
+ const auto bv = b ? ReadScalar<CTYPE>(b) : def; \
+ return av < bv; \
+ }
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
+#undef FLATBUFFERS_TD
+ default: {
+ FLATBUFFERS_ASSERT(false && "scalar type expected");
+ return false;
+ }
+ }
+}
+
+static bool CompareTablesByScalarKey(const Offset<Table> *_a,
+ const Offset<Table> *_b,
+ const FieldDef &key) {
+ const voffset_t offset = key.value.offset;
+ // Indirect offset pointer to table pointer.
+ auto a = reinterpret_cast<const uint8_t *>(_a) + ReadScalar<uoffset_t>(_a);
+ auto b = reinterpret_cast<const uint8_t *>(_b) + ReadScalar<uoffset_t>(_b);
+ // Fetch field address from table.
+ a = reinterpret_cast<const Table *>(a)->GetAddressOf(offset);
+ b = reinterpret_cast<const Table *>(b)->GetAddressOf(offset);
+ return CompareSerializedScalars(a, b, key);
+}
+
+static bool CompareTablesByStringKey(const Offset<Table> *_a,
+ const Offset<Table> *_b,
+ const FieldDef &key) {
+ const voffset_t offset = key.value.offset;
+ // Indirect offset pointer to table pointer.
+ auto a = reinterpret_cast<const uint8_t *>(_a) + ReadScalar<uoffset_t>(_a);
+ auto b = reinterpret_cast<const uint8_t *>(_b) + ReadScalar<uoffset_t>(_b);
+ // Fetch field address from table.
+ a = reinterpret_cast<const Table *>(a)->GetAddressOf(offset);
+ b = reinterpret_cast<const Table *>(b)->GetAddressOf(offset);
+ if (a && b) {
+ // Indirect offset pointer to string pointer.
+ a += ReadScalar<uoffset_t>(a);
+ b += ReadScalar<uoffset_t>(b);
+ return *reinterpret_cast<const String *>(a) <
+ *reinterpret_cast<const String *>(b);
+ } else {
+ return a ? true : false;
+ }
+}
+
+static void SwapSerializedTables(Offset<Table> *a, Offset<Table> *b) {
+ // These are serialized offsets, so are relative where they are
+ // stored in memory, so compute the distance between these pointers:
+ ptrdiff_t diff = (b - a) * sizeof(Offset<Table>);
+ FLATBUFFERS_ASSERT(diff >= 0); // Guaranteed by SimpleQsort.
+ auto udiff = static_cast<uoffset_t>(diff);
+ a->o = EndianScalar(ReadScalar<uoffset_t>(a) - udiff);
+ b->o = EndianScalar(ReadScalar<uoffset_t>(b) + udiff);
+ std::swap(*a, *b);
+}
+
+// See below for why we need our own sort :(
+template<typename T, typename F, typename S>
+static void SimpleQsort(T *begin, T *end, size_t width, F comparator,
+ S swapper) {
+ if (end - begin <= static_cast<ptrdiff_t>(width)) return;
+ auto l = begin + width;
+ auto r = end;
+ while (l < r) {
+ if (comparator(begin, l)) {
+ r -= width;
+ swapper(l, r);
+ } else {
+ l += width;
+ }
+ }
+ l -= width;
+ swapper(begin, l);
+ SimpleQsort(begin, l, width, comparator, swapper);
+ SimpleQsort(r, end, width, comparator, swapper);
+}
+
+template<typename T> static inline void SingleValueRepack(Value &e, T val) {
+ // Remove leading zeros.
+ if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); }
+}
+
+#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
+// Normalize defaults NaN to unsigned quiet-NaN(0) if value was parsed from
+// hex-float literal.
+static void SingleValueRepack(Value &e, float val) {
+ if (val != val) e.constant = "nan";
+}
+static void SingleValueRepack(Value &e, double val) {
+ if (val != val) e.constant = "nan";
+}
+#endif
+
+template<typename T> static uint64_t EnumDistanceImpl(T e1, T e2) {
+ if (e1 < e2) { std::swap(e1, e2); } // use std for scalars
+ // Signed overflow may occur, use unsigned calculation.
+ // The unsigned overflow is well-defined by C++ standard (modulo 2^n).
+ return static_cast<uint64_t>(e1) - static_cast<uint64_t>(e2);
+}
+
+static bool compareFieldDefs(const FieldDef *a, const FieldDef *b) {
+ auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str());
+ auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str());
+ return a_id < b_id;
+}
+
+static Namespace *GetNamespace(
+ const std::string &qualified_name, std::vector<Namespace *> &namespaces,
+ std::map<std::string, Namespace *> &namespaces_index) {
+ size_t dot = qualified_name.find_last_of('.');
+ std::string namespace_name = (dot != std::string::npos)
+ ? std::string(qualified_name.c_str(), dot)
+ : "";
+ Namespace *&ns = namespaces_index[namespace_name];
+
+ if (!ns) {
+ ns = new Namespace();
+ namespaces.push_back(ns);
+
+ size_t pos = 0;
+
+ for (;;) {
+ dot = qualified_name.find('.', pos);
+ if (dot == std::string::npos) { break; }
+ ns->components.push_back(qualified_name.substr(pos, dot - pos));
+ pos = dot + 1;
+ }
+ }
+
+ return ns;
+}
+
+// Generate a unique hash for a file based on its name and contents (if any).
+static uint64_t HashFile(const char *source_filename, const char *source) {
+ uint64_t hash = 0;
+
+ if (source_filename)
+ hash = HashFnv1a<uint64_t>(StripPath(source_filename).c_str());
+
+ if (source && *source) hash ^= HashFnv1a<uint64_t>(source);
+
+ return hash;
+}
+
+template<typename T> static bool compareName(const T *a, const T *b) {
+ return a->defined_namespace->GetFullyQualifiedName(a->name) <
+ b->defined_namespace->GetFullyQualifiedName(b->name);
+}
+
+template<typename T> static void AssignIndices(const std::vector<T *> &defvec) {
+ // Pre-sort these vectors, such that we can set the correct indices for them.
+ auto vec = defvec;
+ std::sort(vec.begin(), vec.end(), compareName<T>);
+ for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i;
+}
+
+} // namespace
+
+// clang-format off
+const char *const kTypeNames[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
+ IDLTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ nullptr
+};
+
+const char kTypeSizes[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ sizeof(CTYPE),
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+};
+// clang-format on
+
+void Parser::Message(const std::string &msg) {
+ if (!error_.empty()) error_ += "\n"; // log all warnings and errors
+ error_ += file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : "";
+ // clang-format off
+
+ #ifdef _WIN32 // MSVC alike
+ error_ +=
+ "(" + NumToString(line_) + ", " + NumToString(CursorPosition()) + ")";
+ #else // gcc alike
+ if (file_being_parsed_.length()) error_ += ":";
+ error_ += NumToString(line_) + ": " + NumToString(CursorPosition());
+ #endif
+ // clang-format on
+ error_ += ": " + msg;
+}
+
+void Parser::Warning(const std::string &msg) {
+ if (!opts.no_warnings) {
+ Message("warning: " + msg);
+ has_warning_ = true; // for opts.warnings_as_errors
+ }
+}
+
+CheckedError Parser::Error(const std::string &msg) {
+ Message("error: " + msg);
+ return CheckedError(true);
+}
+
+CheckedError Parser::RecurseError() {
+ return Error("maximum parsing depth " + NumToString(parse_depth_counter_) +
+ " reached");
+}
+
+const std::string &Parser::GetPooledString(const std::string &s) const {
+ return *(string_cache_.insert(s).first);
+}
+
+class Parser::ParseDepthGuard {
+ public:
+ explicit ParseDepthGuard(Parser *parser_not_null)
+ : parser_(*parser_not_null), caller_depth_(parser_.parse_depth_counter_) {
+ FLATBUFFERS_ASSERT(caller_depth_ <= (FLATBUFFERS_MAX_PARSING_DEPTH) &&
+ "Check() must be called to prevent stack overflow");
+ parser_.parse_depth_counter_ += 1;
+ }
+
+ ~ParseDepthGuard() { parser_.parse_depth_counter_ -= 1; }
+
+ CheckedError Check() {
+ return caller_depth_ >= (FLATBUFFERS_MAX_PARSING_DEPTH)
+ ? parser_.RecurseError()
+ : CheckedError(false);
+ }
+
+ FLATBUFFERS_DELETE_FUNC(ParseDepthGuard(const ParseDepthGuard &));
+ FLATBUFFERS_DELETE_FUNC(ParseDepthGuard &operator=(const ParseDepthGuard &));
+
+ private:
+ Parser &parser_;
+ const int caller_depth_;
+};
+
+std::string Namespace::GetFullyQualifiedName(const std::string &name,
+ size_t max_components) const {
+ // Early exit if we don't have a defined namespace.
+ if (components.empty() || !max_components) { return name; }
+ std::string stream_str;
+ for (size_t i = 0; i < std::min(components.size(), max_components); i++) {
+ stream_str += components[i];
+ stream_str += '.';
+ }
+ if (!stream_str.empty()) stream_str.pop_back();
+ if (name.length()) {
+ stream_str += '.';
+ stream_str += name;
+ }
+ return stream_str;
+}
+
std::string Parser::TokenToStringId(int t) const {
return t == kTokenIdentifier ? attribute_ : TokenToString(t);
}
@@ -307,10 +481,6 @@
return NoError();
}
-static inline bool IsIdentifierStart(char c) {
- return is_alpha(c) || (c == '_');
-}
-
CheckedError Parser::Next() {
doc_comment_.clear();
bool seen_newline = cursor_ == source_;
@@ -489,10 +659,21 @@
}
const auto has_sign = (c == '+') || (c == '-');
- if (has_sign && IsIdentifierStart(*cursor_)) {
- // '-'/'+' and following identifier - it could be a predefined
- // constant. Return the sign in token_, see ParseSingleValue.
- return NoError();
+ if (has_sign) {
+ // Check for +/-inf which is considered a float constant.
+ if (strncmp(cursor_, "inf", 3) == 0 &&
+ !(IsIdentifierStart(cursor_[3]) || is_digit(cursor_[3]))) {
+ attribute_.assign(cursor_ - 1, cursor_ + 3);
+ token_ = kTokenFloatConstant;
+ cursor_ += 3;
+ return NoError();
+ }
+
+ if (IsIdentifierStart(*cursor_)) {
+ // '-'/'+' and following identifier - it could be a predefined
+ // constant. Return the sign in token_, see ParseSingleValue.
+ return NoError();
+ }
}
auto dot_lvl =
@@ -958,8 +1139,12 @@
"definition");
field->native_inline = field->attributes.Lookup("native_inline") != nullptr;
- if (field->native_inline && !IsStruct(field->value.type))
- return Error("native_inline can only be defined on structs");
+ if (field->native_inline && !IsStruct(field->value.type) &&
+ !IsVectorOfStruct(field->value.type) &&
+ !IsVectorOfTable(field->value.type))
+ return Error(
+ "'native_inline' can only be defined on structs, vector of structs or "
+ "vector of tables");
auto nested = field->attributes.Lookup("nested_flatbuffer");
if (nested) {
@@ -1102,8 +1287,9 @@
uint8_t enum_idx;
if (vector_of_union_types) {
if (vector_of_union_types->size() <= count)
- return Error("union types vector smaller than union values vector"
- " for: " + field->name);
+ return Error(
+ "union types vector smaller than union values vector for: " +
+ field->name);
enum_idx = vector_of_union_types->Get(count);
} else {
ECHECK(atot(constant.c_str(), *this, &enum_idx));
@@ -1323,10 +1509,18 @@
ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
builder_.PushElement(val); \
} else { \
- CTYPE val, valdef; \
- ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
- ECHECK(atot(field->value.constant.c_str(), *this, &valdef)); \
- builder_.AddElement(field_value.offset, val, valdef); \
+ if (field->IsScalarOptional()) { \
+ if (field_value.constant != "null") { \
+ CTYPE val; \
+ ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
+ builder_.AddElement(field_value.offset, val); \
+ } \
+ } else { \
+ CTYPE val, valdef; \
+ ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
+ ECHECK(atot(field->value.constant.c_str(), *this, &valdef)); \
+ builder_.AddElement(field_value.offset, val, valdef); \
+ } \
} \
break;
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
@@ -1390,90 +1584,6 @@
return NoError();
}
-static bool CompareSerializedScalars(const uint8_t *a, const uint8_t *b,
- const FieldDef &key) {
- switch (key.value.type.base_type) {
-#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
- case BASE_TYPE_##ENUM: { \
- CTYPE def = static_cast<CTYPE>(0); \
- if (!a || !b) { StringToNumber(key.value.constant.c_str(), &def); } \
- const auto av = a ? ReadScalar<CTYPE>(a) : def; \
- const auto bv = b ? ReadScalar<CTYPE>(b) : def; \
- return av < bv; \
- }
- FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
-#undef FLATBUFFERS_TD
- default: {
- FLATBUFFERS_ASSERT(false && "scalar type expected");
- return false;
- }
- }
-}
-
-static bool CompareTablesByScalarKey(const Offset<Table> *_a,
- const Offset<Table> *_b,
- const FieldDef &key) {
- const voffset_t offset = key.value.offset;
- // Indirect offset pointer to table pointer.
- auto a = reinterpret_cast<const uint8_t *>(_a) + ReadScalar<uoffset_t>(_a);
- auto b = reinterpret_cast<const uint8_t *>(_b) + ReadScalar<uoffset_t>(_b);
- // Fetch field address from table.
- a = reinterpret_cast<const Table *>(a)->GetAddressOf(offset);
- b = reinterpret_cast<const Table *>(b)->GetAddressOf(offset);
- return CompareSerializedScalars(a, b, key);
-}
-
-static bool CompareTablesByStringKey(const Offset<Table> *_a,
- const Offset<Table> *_b,
- const FieldDef &key) {
- const voffset_t offset = key.value.offset;
- // Indirect offset pointer to table pointer.
- auto a = reinterpret_cast<const uint8_t *>(_a) + ReadScalar<uoffset_t>(_a);
- auto b = reinterpret_cast<const uint8_t *>(_b) + ReadScalar<uoffset_t>(_b);
- // Fetch field address from table.
- a = reinterpret_cast<const Table *>(a)->GetAddressOf(offset);
- b = reinterpret_cast<const Table *>(b)->GetAddressOf(offset);
- if (a && b) {
- // Indirect offset pointer to string pointer.
- a += ReadScalar<uoffset_t>(a);
- b += ReadScalar<uoffset_t>(b);
- return *reinterpret_cast<const String *>(a) <
- *reinterpret_cast<const String *>(b);
- } else {
- return a ? true : false;
- }
-}
-
-static void SwapSerializedTables(Offset<Table> *a, Offset<Table> *b) {
- // These are serialized offsets, so are relative where they are
- // stored in memory, so compute the distance between these pointers:
- ptrdiff_t diff = (b - a) * sizeof(Offset<Table>);
- FLATBUFFERS_ASSERT(diff >= 0); // Guaranteed by SimpleQsort.
- auto udiff = static_cast<uoffset_t>(diff);
- a->o = EndianScalar(ReadScalar<uoffset_t>(a) - udiff);
- b->o = EndianScalar(ReadScalar<uoffset_t>(b) + udiff);
- std::swap(*a, *b);
-}
-
-// See below for why we need our own sort :(
-template<typename T, typename F, typename S>
-void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) {
- if (end - begin <= static_cast<ptrdiff_t>(width)) return;
- auto l = begin + width;
- auto r = end;
- while (l < r) {
- if (comparator(begin, l)) {
- r -= width;
- swapper(l, r);
- } else {
- l += width;
- }
- }
- l -= width;
- swapper(begin, l);
- SimpleQsort(begin, l, width, comparator, swapper);
- SimpleQsort(r, end, width, comparator, swapper);
-}
CheckedError Parser::ParseAlignAttribute(const std::string &align_constant,
size_t min_align, size_t *align) {
@@ -1801,22 +1911,6 @@
return Error("cannot parse value starting with: " + TokenToStringId(token_));
}
-// Re-pack helper (ParseSingleValue) to normalize defaults of scalars.
-template<typename T> inline void SingleValueRepack(Value &e, T val) {
- // Remove leading zeros.
- if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); }
-}
-#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
-// Normalize defaults NaN to unsigned quiet-NaN(0) if value was parsed from
-// hex-float literal.
-static inline void SingleValueRepack(Value &e, float val) {
- if (val != val) e.constant = "nan";
-}
-static inline void SingleValueRepack(Value &e, double val) {
- if (val != val) e.constant = "nan";
-}
-#endif
-
CheckedError Parser::ParseFunction(const std::string *name, Value &e) {
ParseDepthGuard depth_guard(this);
ECHECK(depth_guard.Check());
@@ -2088,13 +2182,6 @@
return vals.vec.empty() ? nullptr : vals.vec.back();
}
-template<typename T> static uint64_t EnumDistanceImpl(T e1, T e2) {
- if (e1 < e2) { std::swap(e1, e2); } // use std for scalars
- // Signed overflow may occur, use unsigned calculation.
- // The unsigned overflow is well-defined by C++ standard (modulo 2^n).
- return static_cast<uint64_t>(e1) - static_cast<uint64_t>(e2);
-}
-
uint64_t EnumDef::Distance(const EnumVal *v1, const EnumVal *v2) const {
return IsUInt64() ? EnumDistanceImpl(v1->GetAsUInt64(), v2->GetAsUInt64())
: EnumDistanceImpl(v1->GetAsInt64(), v2->GetAsInt64());
@@ -2312,6 +2399,9 @@
// todo: Convert to the Error in the future?
Warning("underlying type of bit_flags enum must be unsigned");
}
+ if (enum_def->attributes.Lookup("force_align")) {
+ return Error("`force_align` is not a valid attribute for Enums. ");
+ }
EnumValBuilder evb(*this, *enum_def);
EXPECT('{');
// A lot of code generatos expect that an enum is not-empty.
@@ -2448,12 +2538,19 @@
return NoError();
}
+std::vector<IncludedFile> Parser::GetIncludedFiles() const {
+ const auto it = files_included_per_file_.find(file_being_parsed_);
+ if (it == files_included_per_file_.end()) { return {}; }
+
+ return { it->second.cbegin(), it->second.cend() };
+}
+
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::kGo | IDLOptions::kPython | IDLOptions::kJson;
unsigned long langs = opts.lang_to_generate;
return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
}
@@ -2508,12 +2605,6 @@
return full_qualified_name.substr(previous, current - previous);
}
-static bool compareFieldDefs(const FieldDef *a, const FieldDef *b) {
- auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str());
- auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str());
- return a_id < b_id;
-}
-
CheckedError Parser::ParseDecl(const char *filename) {
std::vector<std::string> dc = doc_comment_;
bool fixed = IsIdent("struct");
@@ -2884,7 +2975,11 @@
if (key == "default") {
// Temp: skip non-numeric and non-boolean defaults (enums).
auto numeric = strpbrk(val.c_str(), "0123456789-+.");
- if (IsScalar(type.base_type) && numeric == val.c_str()) {
+ if (IsFloat(type.base_type) &&
+ (val == "inf" || val == "+inf" || val == "-inf")) {
+ // Prefer to be explicit with +inf.
+ field->value.constant = val == "inf" ? "+inf" : val;
+ } else if (IsScalar(type.base_type) && numeric == val.c_str()) {
field->value.constant = val;
} else if (val == "true") {
field->value.constant = val;
@@ -3032,7 +3127,8 @@
case kTokenIntegerConstant:
case kTokenFloatConstant: NEXT(); break;
default:
- if (IsIdent("true") || IsIdent("false") || IsIdent("null")) {
+ if (IsIdent("true") || IsIdent("false") || IsIdent("null") ||
+ IsIdent("inf")) {
NEXT();
} else
return TokenError();
@@ -3245,32 +3341,79 @@
for (auto val_it = enum_def.Vals().begin();
val_it != enum_def.Vals().end(); ++val_it) {
auto &val = **val_it;
+
if (!(opts.lang_to_generate != 0 && SupportsAdvancedUnionFeatures()) &&
(IsStruct(val.union_type) || IsString(val.union_type)))
+
return Error(
"only tables can be union elements in the generated language: " +
val.name);
}
}
}
+
+ auto err = CheckPrivateLeak();
+ if (err.Check()) return err;
+
// Parse JSON object only if the scheme has been parsed.
if (token_ == '{') { ECHECK(DoParseJson()); }
- EXPECT(kTokenEof);
return NoError();
}
-// Generate a unique hash for a file based on its name and contents (if any).
-static uint64_t HashFile(const char *source_filename, const char *source) {
- uint64_t hash = 0;
+CheckedError Parser::CheckPrivateLeak() {
+ if (!opts.no_leak_private_annotations) return NoError();
+ // Iterate over all structs/tables to validate we arent leaking
+ // any private (structs/tables/enums)
+ for (auto it = structs_.vec.begin(); it != structs_.vec.end(); it++) {
+ auto &struct_def = **it;
+ for (auto fld_it = struct_def.fields.vec.begin();
+ fld_it != struct_def.fields.vec.end(); ++fld_it) {
+ auto &field = **fld_it;
- if (source_filename)
- hash = HashFnv1a<uint64_t>(StripPath(source_filename).c_str());
-
- if (source && *source) hash ^= HashFnv1a<uint64_t>(source);
-
- return hash;
+ if (field.value.type.enum_def) {
+ auto err =
+ CheckPrivatelyLeakedFields(struct_def, *field.value.type.enum_def);
+ if (err.Check()) { return err; }
+ } else if (field.value.type.struct_def) {
+ auto err = CheckPrivatelyLeakedFields(struct_def,
+ *field.value.type.struct_def);
+ if (err.Check()) { return err; }
+ }
+ }
+ }
+ // Iterate over all enums to validate we arent leaking
+ // any private (structs/tables)
+ for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) {
+ auto &enum_def = **it;
+ if (enum_def.is_union) {
+ for (auto val_it = enum_def.Vals().begin();
+ val_it != enum_def.Vals().end(); ++val_it) {
+ auto &val = **val_it;
+ if (val.union_type.struct_def) {
+ auto err =
+ CheckPrivatelyLeakedFields(enum_def, *val.union_type.struct_def);
+ if (err.Check()) { return err; }
+ }
+ }
+ }
+ }
+ return NoError();
}
+CheckedError Parser::CheckPrivatelyLeakedFields(const Definition &def,
+ const Definition &value_type) {
+ if (!opts.no_leak_private_annotations) return NoError();
+ const auto is_private = def.attributes.Lookup("private");
+ const auto is_field_private = value_type.attributes.Lookup("private");
+ if (!is_private && is_field_private) {
+ return Error(
+ "Leaking private implementation, verify all objects have similar "
+ "annotations");
+ }
+ return NoError();
+}
+
+
CheckedError Parser::DoParse(const char *source, const char **include_paths,
const char *source_filename,
const char *include_filename) {
@@ -3285,7 +3428,7 @@
if (included_files_.find(source_hash) == included_files_.end()) {
included_files_[source_hash] = include_filename ? include_filename : "";
- files_included_per_file_[source_filename] = std::set<std::string>();
+ files_included_per_file_[source_filename] = std::set<IncludedFile>();
} else {
return NoError();
}
@@ -3333,8 +3476,12 @@
}
if (filepath.empty())
return Error("unable to locate include file: " + name);
- if (source_filename)
- files_included_per_file_[source_filename].insert(filepath);
+ if (source_filename) {
+ IncludedFile included_file;
+ included_file.filename = filepath;
+ included_file.schema_name = name;
+ files_included_per_file_[source_filename].insert(included_file);
+ }
std::string contents;
bool file_loaded = LoadFile(filepath.c_str(), true, &contents);
@@ -3423,6 +3570,7 @@
ECHECK(ParseDecl(source_filename));
}
}
+ EXPECT(kTokenEof);
if (opts.warnings_as_errors && has_warning_) {
return Error("treating warnings as errors, failed due to above warnings");
}
@@ -3470,11 +3618,11 @@
// Workaround the lack of const accessor in C++98 maps.
auto &new_files =
- (*const_cast<std::map<std::string, std::set<std::string>> *>(
+ (*const_cast<std::map<std::string, std::set<IncludedFile>> *>(
&files_included_per_file_))[current];
for (auto it = new_files.begin(); it != new_files.end(); ++it) {
- if (included_files.find(*it) == included_files.end())
- to_process.push_back(*it);
+ if (included_files.find(it->filename) == included_files.end())
+ to_process.push_back(it->filename);
}
}
@@ -3483,18 +3631,6 @@
// Schema serialization functionality:
-template<typename T> bool compareName(const T *a, const T *b) {
- return a->defined_namespace->GetFullyQualifiedName(a->name) <
- b->defined_namespace->GetFullyQualifiedName(b->name);
-}
-
-template<typename T> void AssignIndices(const std::vector<T *> &defvec) {
- // Pre-sort these vectors, such that we can set the correct indices for them.
- auto vec = defvec;
- std::sort(vec.begin(), vec.end(), compareName<T>);
- for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i;
-}
-
void Parser::Serialize() {
builder_.Clear();
AssignIndices(structs_.vec);
@@ -3535,7 +3671,7 @@
// frc971 modification to make file paths in schemas deterministic.
const auto filename__ = builder_.CreateSharedString(f->first);
for (auto i = f->second.begin(); i != f->second.end(); i++) {
- included_files.push_back(builder_.CreateSharedString(*i));
+ included_files.push_back(builder_.CreateSharedString(i->schema_name));
}
const auto included_files__ = builder_.CreateVector(included_files);
included_files.clear();
@@ -3563,32 +3699,6 @@
}
}
-static Namespace *GetNamespace(
- const std::string &qualified_name, std::vector<Namespace *> &namespaces,
- std::map<std::string, Namespace *> &namespaces_index) {
- size_t dot = qualified_name.find_last_of('.');
- std::string namespace_name = (dot != std::string::npos)
- ? std::string(qualified_name.c_str(), dot)
- : "";
- Namespace *&ns = namespaces_index[namespace_name];
-
- if (!ns) {
- ns = new Namespace();
- namespaces.push_back(ns);
-
- size_t pos = 0;
-
- for (;;) {
- dot = qualified_name.find('.', pos);
- if (dot == std::string::npos) { break; }
- ns->components.push_back(qualified_name.substr(pos, dot - pos));
- pos = dot + 1;
- }
- }
-
- return ns;
-}
-
// frc971 modification to make declaration files in schemas deterministic.
// TODO(james): Figure out a clean way to make this workspace root relative.
namespace {
@@ -3636,6 +3746,14 @@
delete field_def;
return false;
}
+ if (field_def->key) {
+ if (has_key) {
+ // only one field may be set as key
+ delete field_def;
+ return false;
+ }
+ has_key = true;
+ }
if (fixed) {
// Recompute padding since that's currently not serialized.
auto size = InlineSize(field_def->value.type);
@@ -3993,7 +4111,9 @@
++s) {
for (auto f = s->included_filenames()->begin();
f != s->included_filenames()->end(); ++f) {
- files_included_per_file_[s->filename()->str()].insert(f->str());
+ IncludedFile included_file;
+ included_file.filename = f->str();
+ files_included_per_file_[s->filename()->str()].insert(included_file);
}
}
diff --git a/third_party/flatbuffers/src/namer.h b/third_party/flatbuffers/src/namer.h
index 6c539cb..8fd8354 100644
--- a/third_party/flatbuffers/src/namer.h
+++ b/third_party/flatbuffers/src/namer.h
@@ -1,7 +1,6 @@
#ifndef FLATBUFFERS_NAMER
#define FLATBUFFERS_NAMER
-#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
@@ -62,6 +61,16 @@
// e.g. `Enum::MyVariant` uses `::`.
std::string enum_variant_seperator;
+ // Configures, when formatting code, whether symbols are checked against
+ // keywords and escaped before or after case conversion. It does not make
+ // sense to do so before, but its legacy behavior. :shrug:
+ // TODO(caspern): Deprecate.
+ enum class Escape {
+ BeforeConvertingCase,
+ AfterConvertingCase,
+ };
+ Escape escape_keywords;
+
// Namespaces
// e.g. `namespace my_namespace {}`
@@ -95,64 +104,55 @@
std::string filename_suffix;
// Extension for generated files, e.g. ".cpp" or ".rs".
std::string filename_extension;
-
- // This is a temporary helper function for code generators to call until all
- // code generators are using `Namer`. After that point, we can centralize
- // flag-overriding logic into flatc.cpp
- Config WithFlagOptions(const IDLOptions &opts,
- const std::string &path) const {
- Config result = *this;
- result.object_prefix = opts.object_prefix;
- result.object_suffix = opts.object_suffix;
- result.output_path = path;
- result.filename_suffix = opts.filename_suffix;
- return result;
- }
};
Namer(Config config, std::set<std::string> keywords)
: config_(config), keywords_(std::move(keywords)) {}
- std::string Type(const std::string &s) const {
- return Format(s, config_.types);
+ virtual ~Namer() {}
+
+ template<typename T> std::string Method(const T &s) const {
+ return Method(s.name);
}
- std::string Method(const std::string &s) const {
+ virtual std::string Method(const std::string &pre,
+ const std::string &mid,
+ const std::string &suf) const {
+ return Format(pre + "_" + mid + "_" + suf, config_.methods);
+ }
+ virtual std::string Method(const std::string &pre,
+ const std::string &suf) const {
+ return Format(pre + "_" + suf, config_.methods);
+ }
+ virtual std::string Method(const std::string &s) const {
return Format(s, config_.methods);
}
- std::string Constant(const std::string &s) const {
+ virtual std::string Constant(const std::string &s) const {
return Format(s, config_.constants);
}
- std::string Function(const std::string &s) const {
+ virtual std::string Function(const std::string &s) const {
return Format(s, config_.functions);
}
- std::string Field(const std::string &s) const {
- return Format(s, config_.fields);
- }
-
- std::string Variable(const std::string &s) const {
+ virtual std::string Variable(const std::string &s) const {
return Format(s, config_.variables);
}
- std::string Variant(const std::string &s) const {
- return Format(s, config_.variants);
+ template<typename T>
+ std::string Variable(const std::string &p, const T &s) const {
+ return Format(p + "_" + s.name, config_.variables);
+ }
+ virtual std::string Variable(const std::string &p,
+ const std::string &s) const {
+ return Format(p + "_" + s, config_.variables);
}
- std::string EnumVariant(const std::string &e, const std::string v) const {
- return Type(e) + config_.enum_variant_seperator + Variant(v);
- }
-
- std::string ObjectType(const std::string &s) const {
- return config_.object_prefix + Type(s) + config_.object_suffix;
- }
-
- std::string Namespace(const std::string &s) const {
+ virtual std::string Namespace(const std::string &s) const {
return Format(s, config_.namespaces);
}
- std::string Namespace(const std::vector<std::string> &ns) const {
+ virtual std::string Namespace(const std::vector<std::string> &ns) const {
std::string result;
for (auto it = ns.begin(); it != ns.end(); it++) {
if (it != ns.begin()) result += config_.namespace_seperator;
@@ -161,26 +161,32 @@
return result;
}
- std::string NamespacedType(const std::vector<std::string> &ns,
- const std::string &s) const {
- return Namespace(ns) + config_.namespace_seperator + Type(s);
+ virtual std::string NamespacedType(const std::vector<std::string> &ns,
+ const std::string &s) const {
+ return (ns.empty() ? "" : (Namespace(ns) + config_.namespace_seperator)) +
+ Type(s);
}
// Returns `filename` with the right casing, suffix, and extension.
- std::string File(const std::string &filename,
- SkipFile skips = SkipFile::None) const {
+ virtual std::string File(const std::string &filename,
+ SkipFile skips = SkipFile::None) const {
const bool skip_suffix = (skips & SkipFile::Suffix) != SkipFile::None;
const bool skip_ext = (skips & SkipFile::Extension) != SkipFile::None;
return ConvertCase(filename, config_.filenames, Case::kUpperCamel) +
(skip_suffix ? "" : config_.filename_suffix) +
(skip_ext ? "" : config_.filename_extension);
}
+ template<typename T>
+ std::string File(const T &f, SkipFile skips = SkipFile::None) const {
+ return File(f.name, skips);
+ }
+
// Formats `directories` prefixed with the output_path and joined with the
// right seperator. Output path prefixing and the trailing separator may be
// skiped using `skips`.
// Callers may want to use `EnsureDirExists` with the result.
- std::string Directories(const std::vector<std::string> &directories,
- SkipDir skips = SkipDir::None) const {
+ virtual std::string Directories(const std::vector<std::string> &directories,
+ SkipDir skips = SkipDir::None) const {
const bool skip_output_path =
(skips & SkipDir::OutputPath) != SkipDir::None;
const bool skip_trailing_seperator =
@@ -194,7 +200,7 @@
return result;
}
- std::string EscapeKeyword(const std::string &name) const {
+ virtual std::string EscapeKeyword(const std::string &name) const {
if (keywords_.find(name) == keywords_.end()) {
return name;
} else {
@@ -202,12 +208,55 @@
}
}
- private:
- std::string Format(const std::string &s, Case casing) const {
- // NOTE: If you need to escape keywords after converting case, which would
- // make more sense than this, make it a config option.
- return ConvertCase(EscapeKeyword(s), casing, Case::kLowerCamel);
+ virtual std::string Type(const std::string &s) const {
+ return Format(s, config_.types);
}
+ virtual std::string Type(const std::string &t, const std::string &s) const {
+ return Format(t + "_" + s, config_.types);
+ }
+
+ virtual std::string ObjectType(const std::string &s) const {
+ return config_.object_prefix + Type(s) + config_.object_suffix;
+ }
+
+ virtual std::string Field(const std::string &s) const {
+ return Format(s, config_.fields);
+ }
+
+ virtual std::string Variant(const std::string &s) const {
+ return Format(s, config_.variants);
+ }
+
+ virtual std::string Format(const std::string &s, Case casing) const {
+ if (config_.escape_keywords == Config::Escape::BeforeConvertingCase) {
+ return ConvertCase(EscapeKeyword(s), casing, Case::kLowerCamel);
+ } else {
+ return EscapeKeyword(ConvertCase(s, casing, Case::kLowerCamel));
+ }
+ }
+
+ // Denamespaces a string (e.g. The.Quick.Brown.Fox) by returning the last part
+ // after the `delimiter` (Fox) and placing the rest in `namespace_prefix`
+ // (The.Quick.Brown).
+ virtual std::string Denamespace(const std::string &s,
+ std::string &namespace_prefix,
+ const char delimiter = '.') const {
+ const size_t pos = s.find_last_of(delimiter);
+ if (pos == std::string::npos) {
+ namespace_prefix = "";
+ return s;
+ }
+ namespace_prefix = s.substr(0, pos);
+ return s.substr(pos + 1);
+ }
+
+ // Same as above, but disregards the prefix.
+ virtual std::string Denamespace(const std::string &s,
+ const char delimiter = '.') const {
+ std::string prefix;
+ return Denamespace(s, prefix, delimiter);
+ }
+
const Config config_;
const std::set<std::string> keywords_;
};
diff --git a/third_party/flatbuffers/src/reflection.cpp b/third_party/flatbuffers/src/reflection.cpp
index 2d92229..7549859 100644
--- a/third_party/flatbuffers/src/reflection.cpp
+++ b/third_party/flatbuffers/src/reflection.cpp
@@ -22,6 +22,238 @@
namespace flatbuffers {
+namespace {
+
+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) {
+ auto offset = parent_table.GetOptionalFieldOffset(field_offset);
+ if (required && !offset) { return false; }
+
+ return !offset ||
+ v.VerifyFieldStruct(reinterpret_cast<const uint8_t *>(&parent_table),
+ offset, obj.bytesize(), obj.minalign());
+}
+
+static bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
+ 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; }
+
+ return !p || v.VerifyVectorOrString(p, obj.bytesize());
+}
+
+// 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 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;
+ auto elem_type = fb_enum->values()->Get(utype)->union_type();
+ switch (elem_type->base_type()) {
+ case reflection::BaseType::Obj: {
+ auto elem_obj = schema.objects()->Get(elem_type->index());
+ if (elem_obj->is_struct()) {
+ return v.VerifyFromPointer(elem, elem_obj->bytesize());
+ } else {
+ return VerifyObject(v, schema, *elem_obj,
+ reinterpret_cast<const flatbuffers::Table *>(elem),
+ true);
+ }
+ }
+ case reflection::BaseType::String:
+ return v.VerifyString(
+ reinterpret_cast<const flatbuffers::String *>(elem));
+ default: return false;
+ }
+}
+
+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::BaseType::Vector);
+ if (!table.VerifyField<uoffset_t>(v, vec_field.offset(), sizeof(uoffset_t)))
+ return false;
+
+ switch (vec_field.type()->element()) {
+ case reflection::BaseType::UType:
+ return v.VerifyVector(flatbuffers::GetFieldV<uint8_t>(table, vec_field));
+ case reflection::BaseType::Bool:
+ case reflection::BaseType::Byte:
+ case reflection::BaseType::UByte:
+ return v.VerifyVector(flatbuffers::GetFieldV<int8_t>(table, vec_field));
+ case reflection::BaseType::Short:
+ case reflection::BaseType::UShort:
+ return v.VerifyVector(flatbuffers::GetFieldV<int16_t>(table, vec_field));
+ case reflection::BaseType::Int:
+ case reflection::BaseType::UInt:
+ return v.VerifyVector(flatbuffers::GetFieldV<int32_t>(table, vec_field));
+ case reflection::BaseType::Long:
+ case reflection::BaseType::ULong:
+ return v.VerifyVector(flatbuffers::GetFieldV<int64_t>(table, vec_field));
+ case reflection::BaseType::Float:
+ return v.VerifyVector(flatbuffers::GetFieldV<float>(table, vec_field));
+ case reflection::BaseType::Double:
+ return v.VerifyVector(flatbuffers::GetFieldV<double>(table, vec_field));
+ case reflection::BaseType::String: {
+ auto vec_string =
+ flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::String>>(
+ table, vec_field);
+ if (v.VerifyVector(vec_string) && v.VerifyVectorOfStrings(vec_string)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ case reflection::BaseType::Obj: {
+ auto obj = schema.objects()->Get(vec_field.type()->index());
+ if (obj->is_struct()) {
+ return VerifyVectorOfStructs(v, table, vec_field.offset(), *obj,
+ vec_field.required());
+ } else {
+ auto vec =
+ flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::Table>>(
+ table, vec_field);
+ if (!v.VerifyVector(vec)) return false;
+ if (!vec) return true;
+ for (uoffset_t j = 0; j < vec->size(); j++) {
+ if (!VerifyObject(v, schema, *obj, vec->Get(j), true)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ case reflection::BaseType::Union: {
+ auto vec = flatbuffers::GetFieldV<flatbuffers::Offset<uint8_t>>(
+ table, vec_field);
+ if (!v.VerifyVector(vec)) return false;
+ if (!vec) return true;
+ auto type_vec = table.GetPointer<Vector<uint8_t> *>(vec_field.offset() -
+ sizeof(voffset_t));
+ if (!v.VerifyVector(type_vec)) return false;
+ for (uoffset_t j = 0; j < vec->size(); j++) {
+ // get union type from the prev field
+ auto utype = type_vec->Get(j);
+ auto elem = vec->Get(j);
+ if (!VerifyUnion(v, schema, utype, elem, vec_field)) return false;
+ }
+ return true;
+ }
+ case reflection::BaseType::Vector:
+ case reflection::BaseType::None:
+ default: FLATBUFFERS_ASSERT(false); return false;
+ }
+}
+
+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++) {
+ auto field_def = obj.fields()->Get(i);
+ switch (field_def->type()->base_type()) {
+ case reflection::BaseType::None: FLATBUFFERS_ASSERT(false); break;
+ case reflection::BaseType::UType:
+ if (!table->VerifyField<uint8_t>(v, field_def->offset(),
+ sizeof(uint8_t)))
+ return false;
+ break;
+ case reflection::BaseType::Bool:
+ case reflection::BaseType::Byte:
+ case reflection::BaseType::UByte:
+ if (!table->VerifyField<int8_t>(v, field_def->offset(), sizeof(int8_t)))
+ return false;
+ break;
+ case reflection::BaseType::Short:
+ case reflection::BaseType::UShort:
+ if (!table->VerifyField<int16_t>(v, field_def->offset(),
+ sizeof(int16_t)))
+ return false;
+ break;
+ case reflection::BaseType::Int:
+ case reflection::BaseType::UInt:
+ if (!table->VerifyField<int32_t>(v, field_def->offset(),
+ sizeof(int32_t)))
+ return false;
+ break;
+ case reflection::BaseType::Long:
+ case reflection::BaseType::ULong:
+ if (!table->VerifyField<int64_t>(v, field_def->offset(),
+ sizeof(int64_t)))
+ return false;
+ break;
+ case reflection::BaseType::Float:
+ if (!table->VerifyField<float>(v, field_def->offset(), sizeof(float)))
+ return false;
+ break;
+ case reflection::BaseType::Double:
+ if (!table->VerifyField<double>(v, field_def->offset(), sizeof(double)))
+ return false;
+ break;
+ case reflection::BaseType::String:
+ if (!table->VerifyField<uoffset_t>(v, field_def->offset(),
+ sizeof(uoffset_t)) ||
+ !v.VerifyString(flatbuffers::GetFieldS(*table, *field_def))) {
+ return false;
+ }
+ break;
+ case reflection::BaseType::Vector:
+ if (!VerifyVector(v, schema, *table, *field_def)) return false;
+ break;
+ case reflection::BaseType::Obj: {
+ auto child_obj = schema.objects()->Get(field_def->type()->index());
+ if (child_obj->is_struct()) {
+ if (!VerifyStruct(v, *table, field_def->offset(), *child_obj,
+ field_def->required())) {
+ return false;
+ }
+ } else {
+ if (!VerifyObject(v, schema, *child_obj,
+ flatbuffers::GetFieldT(*table, *field_def),
+ field_def->required())) {
+ return false;
+ }
+ }
+ break;
+ }
+ case reflection::BaseType::Union: {
+ // get union type from the prev field
+ voffset_t utype_offset = field_def->offset() - sizeof(voffset_t);
+ auto utype = table->GetField<uint8_t>(utype_offset, 0);
+ auto uval = reinterpret_cast<const uint8_t *>(
+ flatbuffers::GetFieldT(*table, *field_def));
+ if (!VerifyUnion(v, schema, utype, uval, *field_def)) { return false; }
+ break;
+ }
+ default: FLATBUFFERS_ASSERT(false); break;
+ }
+ }
+
+ if (!v.EndTable()) return false;
+
+ return true;
+}
+
+
+} // namespace
+
int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data) {
// clang-format off
#define FLATBUFFERS_GET(T) static_cast<int64_t>(ReadScalar<T>(data))
@@ -120,6 +352,23 @@
}
}
+void ForAllFields(const reflection::Object *object, bool reverse,
+ std::function<void(const reflection::Field *)> func) {
+ std::vector<uint32_t> field_to_id_map;
+ field_to_id_map.resize(object->fields()->size());
+
+ // Create the mapping of field ID to the index into the vector.
+ for (uint32_t i = 0; i < object->fields()->size(); ++i) {
+ auto field = object->fields()->Get(i);
+ field_to_id_map[field->id()] = i;
+ }
+
+ for (size_t i = 0; i < field_to_id_map.size(); ++i) {
+ func(object->fields()->Get(
+ field_to_id_map[reverse ? field_to_id_map.size() - i + 1 : i]));
+ }
+}
+
void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val) {
// clang-format off
#define FLATBUFFERS_SET(T) WriteScalar(data, static_cast<T>(val))
@@ -367,12 +616,8 @@
return flatbuf.data() + insertion_point + root_offset;
}
-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());
-}
+
+
Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const reflection::Schema &schema,
@@ -498,231 +743,22 @@
}
}
-bool VerifyStruct(flatbuffers::Verifier &v,
- 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; }
-
- return !offset ||
- v.VerifyFieldStruct(reinterpret_cast<const uint8_t *>(&parent_table),
- offset, obj.bytesize(), obj.minalign());
-}
-
-bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
- 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; }
-
- return !p || v.VerifyVectorOrString(p, obj.bytesize());
-}
-
-// forward declare to resolve cyclic deps between VerifyObject and VerifyVector
-bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
- const reflection::Object &obj,
- const flatbuffers::Table *table, bool required);
-
-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;
- auto elem_type = fb_enum->values()->Get(utype)->union_type();
- switch (elem_type->base_type()) {
- case reflection::BaseType::Obj: {
- auto elem_obj = schema.objects()->Get(elem_type->index());
- if (elem_obj->is_struct()) {
- return v.VerifyFromPointer(elem, elem_obj->bytesize());
- } else {
- return VerifyObject(v, schema, *elem_obj,
- reinterpret_cast<const flatbuffers::Table *>(elem),
- true);
- }
- }
- case reflection::BaseType::String:
- return v.VerifyString(
- reinterpret_cast<const flatbuffers::String *>(elem));
- default: return false;
- }
-}
-
-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::BaseType::Vector);
- if (!table.VerifyField<uoffset_t>(v, vec_field.offset(), sizeof(uoffset_t)))
- return false;
-
- switch (vec_field.type()->element()) {
- case reflection::BaseType::UType:
- return v.VerifyVector(flatbuffers::GetFieldV<uint8_t>(table, vec_field));
- case reflection::BaseType::Bool:
- case reflection::BaseType::Byte:
- case reflection::BaseType::UByte:
- return v.VerifyVector(flatbuffers::GetFieldV<int8_t>(table, vec_field));
- case reflection::BaseType::Short:
- case reflection::BaseType::UShort:
- return v.VerifyVector(flatbuffers::GetFieldV<int16_t>(table, vec_field));
- case reflection::BaseType::Int:
- case reflection::BaseType::UInt:
- return v.VerifyVector(flatbuffers::GetFieldV<int32_t>(table, vec_field));
- case reflection::BaseType::Long:
- case reflection::BaseType::ULong:
- return v.VerifyVector(flatbuffers::GetFieldV<int64_t>(table, vec_field));
- case reflection::BaseType::Float:
- return v.VerifyVector(flatbuffers::GetFieldV<float>(table, vec_field));
- case reflection::BaseType::Double:
- return v.VerifyVector(flatbuffers::GetFieldV<double>(table, vec_field));
- case reflection::BaseType::String: {
- auto vec_string =
- flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::String>>(
- table, vec_field);
- if (v.VerifyVector(vec_string) && v.VerifyVectorOfStrings(vec_string)) {
- return true;
- } else {
- return false;
- }
- }
- case reflection::BaseType::Obj: {
- auto obj = schema.objects()->Get(vec_field.type()->index());
- if (obj->is_struct()) {
- return VerifyVectorOfStructs(v, table, vec_field.offset(), *obj,
- vec_field.required());
- } else {
- auto vec =
- flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::Table>>(
- table, vec_field);
- if (!v.VerifyVector(vec)) return false;
- if (!vec) return true;
- for (uoffset_t j = 0; j < vec->size(); j++) {
- if (!VerifyObject(v, schema, *obj, vec->Get(j), true)) {
- return false;
- }
- }
- return true;
- }
- }
- case reflection::BaseType::Union: {
- auto vec = flatbuffers::GetFieldV<flatbuffers::Offset<uint8_t>>(
- table, vec_field);
- if (!v.VerifyVector(vec)) return false;
- if (!vec) return true;
- auto type_vec = table.GetPointer<Vector<uint8_t> *>(vec_field.offset() -
- sizeof(voffset_t));
- if (!v.VerifyVector(type_vec)) return false;
- for (uoffset_t j = 0; j < vec->size(); j++) {
- // get union type from the prev field
- auto utype = type_vec->Get(j);
- auto elem = vec->Get(j);
- if (!VerifyUnion(v, schema, utype, elem, vec_field)) return false;
- }
- return true;
- }
- case reflection::BaseType::Vector:
- case reflection::BaseType::None:
- default: FLATBUFFERS_ASSERT(false); return false;
- }
-}
-
-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++) {
- auto field_def = obj.fields()->Get(i);
- switch (field_def->type()->base_type()) {
- case reflection::BaseType::None: FLATBUFFERS_ASSERT(false); break;
- case reflection::BaseType::UType:
- if (!table->VerifyField<uint8_t>(v, field_def->offset(),
- sizeof(uint8_t)))
- return false;
- break;
- case reflection::BaseType::Bool:
- case reflection::BaseType::Byte:
- case reflection::BaseType::UByte:
- if (!table->VerifyField<int8_t>(v, field_def->offset(), sizeof(int8_t)))
- return false;
- break;
- case reflection::BaseType::Short:
- case reflection::BaseType::UShort:
- if (!table->VerifyField<int16_t>(v, field_def->offset(),
- sizeof(int16_t)))
- return false;
- break;
- case reflection::BaseType::Int:
- case reflection::BaseType::UInt:
- if (!table->VerifyField<int32_t>(v, field_def->offset(),
- sizeof(int32_t)))
- return false;
- break;
- case reflection::BaseType::Long:
- case reflection::BaseType::ULong:
- if (!table->VerifyField<int64_t>(v, field_def->offset(),
- sizeof(int64_t)))
- return false;
- break;
- case reflection::BaseType::Float:
- if (!table->VerifyField<float>(v, field_def->offset(), sizeof(float)))
- return false;
- break;
- case reflection::BaseType::Double:
- if (!table->VerifyField<double>(v, field_def->offset(), sizeof(double)))
- return false;
- break;
- case reflection::BaseType::String:
- if (!table->VerifyField<uoffset_t>(v, field_def->offset(),
- sizeof(uoffset_t)) ||
- !v.VerifyString(flatbuffers::GetFieldS(*table, *field_def))) {
- return false;
- }
- break;
- case reflection::BaseType::Vector:
- if (!VerifyVector(v, schema, *table, *field_def)) return false;
- break;
- case reflection::BaseType::Obj: {
- auto child_obj = schema.objects()->Get(field_def->type()->index());
- if (child_obj->is_struct()) {
- if (!VerifyStruct(v, *table, field_def->offset(), *child_obj,
- field_def->required())) {
- return false;
- }
- } else {
- if (!VerifyObject(v, schema, *child_obj,
- flatbuffers::GetFieldT(*table, *field_def),
- field_def->required())) {
- return false;
- }
- }
- break;
- }
- case reflection::BaseType::Union: {
- // get union type from the prev field
- voffset_t utype_offset = field_def->offset() - sizeof(voffset_t);
- auto utype = table->GetField<uint8_t>(utype_offset, 0);
- auto uval = reinterpret_cast<const uint8_t *>(
- flatbuffers::GetFieldT(*table, *field_def));
- if (!VerifyUnion(v, schema, utype, uval, *field_def)) { return false; }
- break;
- }
- default: FLATBUFFERS_ASSERT(false); break;
- }
- }
-
- if (!v.EndTable()) return false;
-
- return true;
-}
bool Verify(const reflection::Schema &schema, const reflection::Object &root,
- const uint8_t *buf, size_t length, uoffset_t max_depth /*= 64*/,
- uoffset_t max_tables /*= 1000000*/) {
+ const uint8_t *const buf, const size_t length,
+ const uoffset_t max_depth, const uoffset_t max_tables) {
Verifier v(buf, length, max_depth, max_tables);
- return VerifyObject(v, schema, root, flatbuffers::GetAnyRoot(buf), true);
+ return VerifyObject(v, schema, root, flatbuffers::GetAnyRoot(buf),
+ /*required=*/true);
+}
+
+bool VerifySizePrefixed(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) {
+ Verifier v(buf, length, max_depth, max_tables);
+ return VerifyObject(v, schema, root, flatbuffers::GetAnySizePrefixedRoot(buf),
+ /*required=*/true);
}
} // namespace flatbuffers
diff --git a/third_party/flatbuffers/src/util.cpp b/third_party/flatbuffers/src/util.cpp
index a1ed6c1..df324e8 100644
--- a/third_party/flatbuffers/src/util.cpp
+++ b/third_party/flatbuffers/src/util.cpp
@@ -17,13 +17,14 @@
// clang-format off
// Dont't remove `format off`, it prevent reordering of win-includes.
+#include <cstring>
#if defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__) || \
defined(__QNXNTO__)
# define _POSIX_C_SOURCE 200809L
# define _XOPEN_SOURCE 700L
#endif
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
@@ -34,7 +35,9 @@
# include <crtdbg.h>
# endif
# include <windows.h> // Must be included before <direct.h>
-# include <direct.h>
+# ifndef __CYGWIN__
+# include <direct.h>
+# endif
# include <winbase.h>
# undef interface // This is also important because of reasons
#endif
@@ -46,19 +49,21 @@
#include <clocale>
#include <cstdlib>
-#include <functional>
#include <fstream>
+#include <functional>
#include "flatbuffers/base.h"
namespace flatbuffers {
-bool FileExistsRaw(const char *name) {
+namespace {
+
+static bool FileExistsRaw(const char *name) {
std::ifstream ifs(name);
return ifs.good();
}
-bool LoadFileRaw(const char *name, bool binary, std::string *buf) {
+static bool LoadFileRaw(const char *name, bool binary, std::string *buf) {
if (DirExists(name)) return false;
std::ifstream ifs(name, binary ? std::ifstream::binary : std::ifstream::in);
if (!ifs.is_open()) return false;
@@ -78,8 +83,124 @@
return !ifs.bad();
}
-static LoadFileFunction g_load_file_function = LoadFileRaw;
-static FileExistsFunction g_file_exists_function = FileExistsRaw;
+LoadFileFunction g_load_file_function = LoadFileRaw;
+FileExistsFunction g_file_exists_function = FileExistsRaw;
+
+static std::string ToCamelCase(const std::string &input, bool first) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) {
+ if (!i && first)
+ s += CharToUpper(input[i]);
+ else if (input[i] == '_' && i + 1 < input.length())
+ s += CharToUpper(input[++i]);
+ else
+ s += input[i];
+ }
+ return s;
+}
+
+static std::string ToSnakeCase(const std::string &input, bool screaming) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) {
+ if (i == 0) {
+ s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
+ } else if (input[i] == '_') {
+ s += '_';
+ } else if (!islower(input[i])) {
+ // Prevent duplicate underscores for Upper_Snake_Case strings
+ // and UPPERCASE strings.
+ if (islower(input[i - 1])) { s += '_'; }
+ s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
+ } else {
+ s += screaming ? CharToUpper(input[i]) : input[i];
+ }
+ }
+ return s;
+}
+
+std::string ToAll(const std::string &input,
+ std::function<char(const char)> transform) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) { s += transform(input[i]); }
+ return s;
+}
+
+std::string CamelToSnake(const std::string &input) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) {
+ if (i == 0) {
+ s += CharToLower(input[i]);
+ } else if (input[i] == '_') {
+ s += '_';
+ } else if (!islower(input[i])) {
+ // Prevent duplicate underscores for Upper_Snake_Case strings
+ // and UPPERCASE strings.
+ if (islower(input[i - 1])) { s += '_'; }
+ s += CharToLower(input[i]);
+ } else {
+ s += input[i];
+ }
+ }
+ return s;
+}
+
+std::string DasherToSnake(const std::string &input) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) {
+ if (input[i] == '-') {
+ s += "_";
+ } else {
+ s += input[i];
+ }
+ }
+ return s;
+}
+
+std::string ToDasher(const std::string &input) {
+ std::string s;
+ char p = 0;
+ for (size_t i = 0; i < input.length(); i++) {
+ char const &c = input[i];
+ if (c == '_') {
+ if (i > 0 && p != kPathSeparator &&
+ // The following is a special case to ignore digits after a _. This is
+ // because ThisExample3 would be converted to this_example_3 in the
+ // CamelToSnake conversion, and then dasher would do this-example-3,
+ // but it expects this-example3.
+ !(i + 1 < input.length() && isdigit(input[i + 1])))
+ s += "-";
+ } else {
+ s += c;
+ }
+ p = c;
+ }
+ return s;
+}
+
+
+// Converts foo_bar_123baz_456 to foo_bar123_baz456
+std::string SnakeToSnake2(const std::string &s) {
+ if (s.length() <= 1) return s;
+ std::string result;
+ result.reserve(s.size());
+ for (size_t i = 0; i < s.length() - 1; i++) {
+ if (s[i] == '_' && isdigit(s[i + 1])) {
+ continue; // Move the `_` until after the digits.
+ }
+
+ result.push_back(s[i]);
+
+ if (isdigit(s[i]) && isalpha(s[i + 1]) && islower(s[i + 1])) {
+ result.push_back('_');
+ }
+ }
+ result.push_back(s.back());
+
+ return result;
+}
+
+} // namespace
+
bool LoadFile(const char *name, bool binary, std::string *buf) {
FLATBUFFERS_ASSERT(g_load_file_function);
@@ -155,6 +276,15 @@
return i != std::string::npos ? filepath.substr(0, i) : "";
}
+std::string StripPrefix(const std::string &filepath,
+ const std::string &prefix_to_remove) {
+ if (!strncmp(filepath.c_str(), prefix_to_remove.c_str(),
+ prefix_to_remove.size())) {
+ return filepath.substr(prefix_to_remove.size());
+ }
+ return filepath;
+}
+
std::string ConCatPathFileName(const std::string &path,
const std::string &filename) {
std::string filepath = path;
@@ -202,7 +332,7 @@
#ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
return filepath;
#else
- #ifdef _WIN32
+ #if defined(_WIN32) || defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__)
char abs_path[MAX_PATH];
return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
#else
@@ -296,124 +426,6 @@
return true;
}
-void SetupDefaultCRTReportMode() {
- // clang-format off
-
- #ifdef _MSC_VER
- // By default, send all reports to STDOUT to prevent CI hangs.
- // Enable assert report box [Abort|Retry|Ignore] if a debugger is present.
- const int dbg_mode = (_CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG) |
- (IsDebuggerPresent() ? _CRTDBG_MODE_WNDW : 0);
- (void)dbg_mode; // release mode fix
- // CrtDebug reports to _CRT_WARN channel.
- _CrtSetReportMode(_CRT_WARN, dbg_mode);
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
- // The assert from <assert.h> reports to _CRT_ERROR channel
- _CrtSetReportMode(_CRT_ERROR, dbg_mode);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
- // Internal CRT assert channel?
- _CrtSetReportMode(_CRT_ASSERT, dbg_mode);
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
- #endif
-
- // clang-format on
-}
-
-namespace {
-
-static std::string ToCamelCase(const std::string &input, bool first) {
- std::string s;
- for (size_t i = 0; i < input.length(); i++) {
- if (!i && first)
- s += CharToUpper(input[i]);
- else if (input[i] == '_' && i + 1 < input.length())
- s += CharToUpper(input[++i]);
- else
- s += input[i];
- }
- return s;
-}
-
-static std::string ToSnakeCase(const std::string &input, bool screaming) {
- std::string s;
- for (size_t i = 0; i < input.length(); i++) {
- if (i == 0) {
- s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
- } else if (input[i] == '_') {
- s += '_';
- } else if (!islower(input[i])) {
- // Prevent duplicate underscores for Upper_Snake_Case strings
- // and UPPERCASE strings.
- if (islower(input[i - 1])) { s += '_'; }
- s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
- } else {
- s += screaming ? CharToUpper(input[i]) : input[i];
- }
- }
- return s;
-}
-
-static std::string ToAll(const std::string &input,
- std::function<char(const char)> transform) {
- std::string s;
- for (size_t i = 0; i < input.length(); i++) { s += transform(input[i]); }
- return s;
-}
-
-static std::string CamelToSnake(const std::string &input) {
- std::string s;
- for (size_t i = 0; i < input.length(); i++) {
- if (i == 0) {
- s += CharToLower(input[i]);
- } else if (input[i] == '_') {
- s += '_';
- } else if (!islower(input[i])) {
- // Prevent duplicate underscores for Upper_Snake_Case strings
- // and UPPERCASE strings.
- if (islower(input[i - 1])) { s += '_'; }
- s += CharToLower(input[i]);
- } else {
- s += input[i];
- }
- }
- return s;
-}
-
-static std::string DasherToSnake(const std::string &input) {
- std::string s;
- for (size_t i = 0; i < input.length(); i++) {
- if (input[i] == '-') {
- s += "_";
- } else {
- s += input[i];
- }
- }
- return s;
-}
-
-static std::string ToDasher(const std::string &input) {
- std::string s;
- char p = 0;
- for (size_t i = 0; i < input.length(); i++) {
- char const &c = input[i];
- if (c == '_') {
- if (i > 0 && p != kPathSeparator &&
- // The following is a special case to ignore digits after a _. This is
- // because ThisExample3 would be converted to this_example_3 in the
- // CamelToSnake conversion, and then dasher would do this-example-3,
- // but it expects this-example3.
- !(i + 1 < input.length() && isdigit(input[i + 1])))
- s += "-";
- } else {
- s += c;
- }
- p = c;
- }
- return s;
-}
-
-} // namespace
-
std::string ConvertCase(const std::string &input, Case output_case,
Case input_case) {
if (output_case == Case::kKeep) return input;
@@ -440,6 +452,7 @@
case Case::kAllUpper: return ToAll(input, CharToUpper);
case Case::kAllLower: return ToAll(input, CharToLower);
case Case::kDasher: return ToDasher(input);
+ case Case::kSnake2: return SnakeToSnake2(input);
default:
case Case::kUnknown: return input;
}