123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467 |
- /*
- * Copyright 2014 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // independent from idl_parser, since this code is not needed for most clients
- #include "flatbuffers/flatbuffers.h"
- #include "flatbuffers/idl.h"
- #include "flatbuffers/util.h"
- #include "flatbuffers/code_generators.h"
- #include <algorithm>
- namespace flatbuffers {
- // Convert an underscore_based_indentifier in to camelCase.
- // Also uppercases the first character if first is true.
- std::string MakeCamel(const std::string &in, bool first) {
- std::string s;
- for (size_t i = 0; i < in.length(); i++) {
- if (!i && first)
- s += static_cast<char>(toupper(in[0]));
- else if (in[i] == '_' && i + 1 < in.length())
- s += static_cast<char>(toupper(in[++i]));
- else
- s += in[i];
- }
- return s;
- }
- struct CommentConfig {
- const char *first_line;
- const char *content_line_prefix;
- const char *last_line;
- };
- // Generate a documentation comment, if available.
- void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
- const CommentConfig *config, const char *prefix) {
- if (dc.begin() == dc.end()) {
- // Don't output empty comment blocks with 0 lines of comment content.
- return;
- }
- std::string &code = *code_ptr;
- if (config != nullptr && config->first_line != nullptr) {
- code += std::string(prefix) + std::string(config->first_line) + "\n";
- }
- std::string line_prefix = std::string(prefix) +
- ((config != nullptr && config->content_line_prefix != nullptr) ?
- config->content_line_prefix : "///");
- for (auto it = dc.begin();
- it != dc.end();
- ++it) {
- code += line_prefix + *it + "\n";
- }
- if (config != nullptr && config->last_line != nullptr) {
- code += std::string(prefix) + std::string(config->last_line) + "\n";
- }
- }
- // These arrays need to correspond to the IDLOptions::k enum.
- struct LanguageParameters {
- IDLOptions::Language language;
- // Whether function names in the language typically start with uppercase.
- bool first_camel_upper;
- std::string file_extension;
- std::string string_type;
- std::string bool_type;
- std::string open_curly;
- std::string accessor_type;
- std::string const_decl;
- std::string unsubclassable_decl;
- std::string enum_decl;
- std::string enum_separator;
- std::string getter_prefix;
- std::string getter_suffix;
- std::string inheritance_marker;
- std::string namespace_ident;
- std::string namespace_begin;
- std::string namespace_end;
- std::string set_bb_byteorder;
- std::string get_bb_position;
- std::string get_fbb_offset;
- std::string accessor_prefix;
- std::string accessor_prefix_static;
- std::string optional_suffix;
- std::string includes;
- CommentConfig comment_config;
- };
- LanguageParameters language_parameters[] = {
- {
- IDLOptions::kJava,
- false,
- ".java",
- "String",
- "boolean ",
- " {\n",
- "class ",
- " final ",
- "final ",
- "final class ",
- ";\n",
- "()",
- "",
- " extends ",
- "package ",
- ";",
- "",
- "_bb.order(ByteOrder.LITTLE_ENDIAN); ",
- "position()",
- "offset()",
- "",
- "",
- "",
- "import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n"
- "import com.google.flatbuffers.*;\n\n@SuppressWarnings(\"unused\")\n",
- {
- "/**",
- " *",
- " */",
- },
- },
- {
- IDLOptions::kCSharp,
- true,
- ".cs",
- "string",
- "bool ",
- "\n{\n",
- "struct ",
- " readonly ",
- "",
- "enum ",
- ",\n",
- " { get",
- "} ",
- " : ",
- "namespace ",
- "\n{",
- "\n}\n",
- "",
- "Position",
- "Offset",
- "__p.",
- "Table.",
- "?",
- "using System;\nusing FlatBuffers;\n\n",
- {
- nullptr,
- "///",
- nullptr,
- },
- },
- // TODO: add Go support to the general generator.
- // WARNING: this is currently only used for generating make rules for Go.
- {
- IDLOptions::kGo,
- true,
- ".go",
- "string",
- "bool ",
- "\n{\n",
- "class ",
- "const ",
- " ",
- "class ",
- ";\n",
- "()",
- "",
- "",
- "package ",
- "",
- "",
- "",
- "position()",
- "offset()",
- "",
- "",
- "",
- "import (\n\tflatbuffers \"github.com/google/flatbuffers/go\"\n)",
- {
- nullptr,
- "///",
- nullptr,
- },
- }
- };
- static_assert(sizeof(language_parameters) / sizeof(LanguageParameters) ==
- IDLOptions::kMAX,
- "Please add extra elements to the arrays above.");
- namespace general {
- class GeneralGenerator : public BaseGenerator {
- public:
- GeneralGenerator(const Parser &parser, const std::string &path,
- const std::string &file_name)
- : BaseGenerator(parser, path, file_name, "", "."),
- lang_(language_parameters[parser_.opts.lang]),
- cur_name_space_( nullptr ) {
- assert(parser_.opts.lang <= IDLOptions::kMAX);
- };
- GeneralGenerator &operator=(const GeneralGenerator &);
- bool generate() {
- std::string one_file_code;
- cur_name_space_ = parser_.namespaces_.back();
- for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
- ++it) {
- std::string enumcode;
- auto &enum_def = **it;
- if (!parser_.opts.one_file)
- cur_name_space_ = enum_def.defined_namespace;
- GenEnum(enum_def, &enumcode);
- if (parser_.opts.one_file) {
- one_file_code += enumcode;
- } else {
- if (!SaveType(enum_def.name, *enum_def.defined_namespace,
- enumcode, false)) return false;
- }
- }
- for (auto it = parser_.structs_.vec.begin();
- it != parser_.structs_.vec.end(); ++it) {
- std::string declcode;
- auto &struct_def = **it;
- if (!parser_.opts.one_file)
- cur_name_space_ = struct_def.defined_namespace;
- GenStruct(struct_def, &declcode);
- if (parser_.opts.one_file) {
- one_file_code += declcode;
- } else {
- if (!SaveType(struct_def.name, *struct_def.defined_namespace,
- declcode, true)) return false;
- }
- }
- if (parser_.opts.one_file) {
- return SaveType(file_name_, *parser_.namespaces_.back(),
- one_file_code, true);
- }
- return true;
- }
- // Save out the generated code for a single class while adding
- // declaration boilerplate.
- bool SaveType(const std::string &defname, const Namespace &ns,
- const std::string &classcode, bool needs_includes) {
- if (!classcode.length()) return true;
- std::string code;
- code = code + "// " + FlatBuffersGeneratedWarning();
- std::string namespace_name = FullNamespace(".", ns);
- if (!namespace_name.empty()) {
- code += lang_.namespace_ident + namespace_name + lang_.namespace_begin;
- code += "\n\n";
- }
- if (needs_includes) code += lang_.includes;
- code += classcode;
- if (!namespace_name.empty()) code += lang_.namespace_end;
- auto filename = NamespaceDir(ns) + defname + lang_.file_extension;
- return SaveFile(filename.c_str(), code, false);
- }
- const Namespace *CurrentNameSpace() { return cur_name_space_; }
- std::string FunctionStart(char upper) {
- return std::string() + (lang_.language == IDLOptions::kJava
- ? static_cast<char>(tolower(upper))
- : upper);
- }
- static bool IsEnum(const Type& type) {
- return type.enum_def != nullptr && IsInteger(type.base_type);
- }
- std::string GenTypeBasic(const Type &type, bool enableLangOverrides) {
- static const char *gtypename[] = {
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
- #JTYPE, #NTYPE, #GTYPE,
- FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
- #undef FLATBUFFERS_TD
- };
- if (enableLangOverrides) {
- if (lang_.language == IDLOptions::kCSharp) {
- if (IsEnum(type)) return WrapInNameSpace(*type.enum_def);
- if (type.base_type == BASE_TYPE_STRUCT) {
- return "Offset<" + WrapInNameSpace(*type.struct_def) + ">";
- }
- }
- }
- return gtypename[type.base_type * IDLOptions::kMAX + lang_.language];
- }
- std::string GenTypeBasic(const Type &type) {
- return GenTypeBasic(type, true);
- }
- std::string GenTypePointer(const Type &type) {
- switch (type.base_type) {
- case BASE_TYPE_STRING:
- return lang_.string_type;
- case BASE_TYPE_VECTOR:
- return GenTypeGet(type.VectorType());
- case BASE_TYPE_STRUCT:
- return WrapInNameSpace(*type.struct_def);
- case BASE_TYPE_UNION:
- // Unions in C# use a generic Table-derived type for better type safety
- if (lang_.language == IDLOptions::kCSharp) return "TTable";
- // fall through
- default:
- return "Table";
- }
- }
- std::string GenTypeGet(const Type &type) {
- return IsScalar(type.base_type)
- ? GenTypeBasic(type)
- : GenTypePointer(type);
- }
- // Find the destination type the user wants to receive the value in (e.g.
- // one size higher signed types for unsigned serialized values in Java).
- Type DestinationType(const Type &type, bool vectorelem) {
- if (lang_.language != IDLOptions::kJava) return type;
- switch (type.base_type) {
- // We use int for both uchar/ushort, since that generally means less casting
- // than using short for uchar.
- case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT);
- case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT);
- case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG);
- case BASE_TYPE_VECTOR:
- if (vectorelem)
- return DestinationType(type.VectorType(), vectorelem);
- // else fall thru:
- default: return type;
- }
- }
- std::string GenOffsetType(const StructDef &struct_def) {
- if(lang_.language == IDLOptions::kCSharp) {
- return "Offset<" + WrapInNameSpace(struct_def) + ">";
- } else {
- return "int";
- }
- }
- std::string GenOffsetConstruct(const StructDef &struct_def,
- const std::string &variable_name)
- {
- if(lang_.language == IDLOptions::kCSharp) {
- return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + variable_name +
- ")";
- }
- return variable_name;
- }
- std::string GenVectorOffsetType() {
- if(lang_.language == IDLOptions::kCSharp) {
- return "VectorOffset";
- } else {
- return "int";
- }
- }
- // Generate destination type name
- std::string GenTypeNameDest(const Type &type)
- {
- return GenTypeGet(DestinationType(type, true));
- }
- // Mask to turn serialized value into destination type value.
- std::string DestinationMask(const Type &type, bool vectorelem) {
- if (lang_.language != IDLOptions::kJava) return "";
- switch (type.base_type) {
- case BASE_TYPE_UCHAR: return " & 0xFF";
- case BASE_TYPE_USHORT: return " & 0xFFFF";
- case BASE_TYPE_UINT: return " & 0xFFFFFFFFL";
- case BASE_TYPE_VECTOR:
- if (vectorelem)
- return DestinationMask(type.VectorType(), vectorelem);
- // else fall thru:
- default: return "";
- }
- }
- // Casts necessary to correctly read serialized data
- std::string DestinationCast(const Type &type) {
- if (type.base_type == BASE_TYPE_VECTOR) {
- return DestinationCast(type.VectorType());
- } else {
- switch (lang_.language) {
- case IDLOptions::kJava:
- // Cast necessary to correctly read serialized unsigned values.
- if (type.base_type == BASE_TYPE_UINT) return "(long)";
- break;
- case IDLOptions::kCSharp:
- // Cast from raw integral types to enum.
- if (IsEnum(type)) return "(" + WrapInNameSpace(*type.enum_def) + ")";
- break;
- default:
- break;
- }
- }
- return "";
- }
- // Cast statements for mutator method parameters.
- // In Java, parameters representing unsigned numbers need to be cast down to
- // their respective type. For example, a long holding an unsigned int value
- // would be cast down to int before being put onto the buffer. In C#, one cast
- // directly cast an Enum to its underlying type, which is essential before
- // putting it onto the buffer.
- std::string SourceCast(const Type &type, bool castFromDest) {
- if (type.base_type == BASE_TYPE_VECTOR) {
- return SourceCast(type.VectorType(), castFromDest);
- } else {
- switch (lang_.language) {
- case IDLOptions::kJava:
- if (castFromDest) {
- if (type.base_type == BASE_TYPE_UINT) return "(int)";
- else if (type.base_type == BASE_TYPE_USHORT) return "(short)";
- else if (type.base_type == BASE_TYPE_UCHAR) return "(byte)";
- }
- break;
- case IDLOptions::kCSharp:
- if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + ")";
- break;
- default:
- break;
- }
- }
- return "";
- }
- std::string SourceCast(const Type &type) {
- return SourceCast(type, true);
- }
- std::string SourceCastBasic(const Type &type, bool castFromDest) {
- return IsScalar(type.base_type) ? SourceCast(type, castFromDest) : "";
- }
- std::string SourceCastBasic(const Type &type) {
- return SourceCastBasic(type, true);
- }
- std::string GenEnumDefaultValue(const Value &value) {
- auto enum_def = value.type.enum_def;
- auto vec = enum_def->vals.vec;
- auto default_value = StringToInt(value.constant.c_str());
- auto result = value.constant;
- for (auto it = vec.begin(); it != vec.end(); ++it) {
- auto enum_val = **it;
- if (enum_val.value == default_value) {
- result = WrapInNameSpace(*enum_def) + "." + enum_val.name;
- break;
- }
- }
- return result;
- }
- std::string GenDefaultValue(const Value &value, bool enableLangOverrides) {
- if (enableLangOverrides) {
- // handles both enum case and vector of enum case
- if (lang_.language == IDLOptions::kCSharp &&
- value.type.enum_def != nullptr &&
- value.type.base_type != BASE_TYPE_UNION) {
- return GenEnumDefaultValue(value);
- }
- }
- auto longSuffix = lang_.language == IDLOptions::kJava ? "L" : "";
- switch (value.type.base_type) {
- case BASE_TYPE_FLOAT: return value.constant + "f";
- case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true";
- case BASE_TYPE_ULONG:
- {
- if (lang_.language != IDLOptions::kJava)
- return value.constant;
- // Converts the ulong into its bits signed equivalent
- uint64_t defaultValue = StringToUInt(value.constant.c_str());
- return NumToString(static_cast<int64_t>(defaultValue)) + longSuffix;
- }
- case BASE_TYPE_UINT:
- case BASE_TYPE_LONG: return value.constant + longSuffix;
- default: return value.constant;
- }
- }
- std::string GenDefaultValue(const Value &value) {
- return GenDefaultValue(value, true);
- }
- std::string GenDefaultValueBasic(const Value &value, bool enableLangOverrides) {
- if (!IsScalar(value.type.base_type)) {
- if (enableLangOverrides) {
- if (lang_.language == IDLOptions::kCSharp) {
- switch (value.type.base_type) {
- case BASE_TYPE_STRING:
- return "default(StringOffset)";
- case BASE_TYPE_STRUCT:
- return "default(Offset<" + WrapInNameSpace(*value.type.struct_def) +
- ">)";
- case BASE_TYPE_VECTOR:
- return "default(VectorOffset)";
- default:
- break;
- }
- }
- }
- return "0";
- }
- return GenDefaultValue(value, enableLangOverrides);
- }
- std::string GenDefaultValueBasic(const Value &value) {
- return GenDefaultValueBasic(value, true);
- }
- void GenEnum(EnumDef &enum_def, std::string *code_ptr) {
- std::string &code = *code_ptr;
- if (enum_def.generated) return;
- // Generate enum definitions of the form:
- // public static (final) int name = value;
- // 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, &lang_.comment_config);
- code += std::string("public ") + lang_.enum_decl + enum_def.name;
- if (lang_.language == IDLOptions::kCSharp) {
- code += lang_.inheritance_marker +
- GenTypeBasic(enum_def.underlying_type, false);
- }
- code += lang_.open_curly;
- if (lang_.language == IDLOptions::kJava) {
- code += " private " + enum_def.name + "() { }\n";
- }
- for (auto it = enum_def.vals.vec.begin();
- it != enum_def.vals.vec.end();
- ++it) {
- auto &ev = **it;
- GenComment(ev.doc_comment, code_ptr, &lang_.comment_config, " ");
- if (lang_.language != IDLOptions::kCSharp) {
- code += " public static";
- code += lang_.const_decl;
- code += GenTypeBasic(enum_def.underlying_type, false);
- }
- code += " " + ev.name + " = ";
- code += NumToString(ev.value);
- code += lang_.enum_separator;
- }
- // Generate a generate string table for enum values.
- // We do not do that for C# where this functionality is native.
- if (lang_.language != IDLOptions::kCSharp) {
- // Problem is, if values are very sparse that could generate really big
- // tables. Ideally in that case we generate a map lookup instead, but for
- // the moment we simply don't output a table at all.
- auto range = enum_def.vals.vec.back()->value -
- enum_def.vals.vec.front()->value + 1;
- // Average distance between values above which we consider a table
- // "too sparse". Change at will.
- static const int kMaxSparseness = 5;
- if (range / static_cast<int64_t>(enum_def.vals.vec.size()) < kMaxSparseness) {
- code += "\n public static";
- code += lang_.const_decl;
- code += lang_.string_type;
- code += "[] names = { ";
- auto val = enum_def.vals.vec.front()->value;
- for (auto it = enum_def.vals.vec.begin();
- it != enum_def.vals.vec.end();
- ++it) {
- while (val++ != (*it)->value) code += "\"\", ";
- code += "\"" + (*it)->name + "\", ";
- }
- code += "};\n\n";
- code += " public static ";
- code += lang_.string_type;
- code += " " + MakeCamel("name", lang_.first_camel_upper);
- code += "(int e) { return names[e";
- if (enum_def.vals.vec.front()->value)
- code += " - " + enum_def.vals.vec.front()->name;
- code += "]; }\n";
- }
- }
- // Close the class
- code += "}";
- // Java does not need the closing semi-colon on class definitions.
- code += (lang_.language != IDLOptions::kJava) ? ";" : "";
- code += "\n\n";
- }
- // Returns the function name that is able to read a value of the given type.
- std::string GenGetter(const Type &type) {
- switch (type.base_type) {
- case BASE_TYPE_STRING: return lang_.accessor_prefix + "__string";
- case BASE_TYPE_STRUCT: return lang_.accessor_prefix + "__struct";
- case BASE_TYPE_UNION: return lang_.accessor_prefix + "__union";
- case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
- default: {
- std::string getter =
- lang_.accessor_prefix + "bb." + FunctionStart('G') + "et";
- if (type.base_type == BASE_TYPE_BOOL) {
- getter = "0!=" + getter;
- } else if (GenTypeBasic(type, false) != "byte") {
- getter += MakeCamel(GenTypeBasic(type, false));
- }
- return getter;
- }
- }
- }
- // Direct mutation is only allowed for scalar fields.
- // Hence a setter method will only be generated for such fields.
- std::string GenSetter(const Type &type) {
- if (IsScalar(type.base_type)) {
- std::string setter =
- lang_.accessor_prefix + "bb." + FunctionStart('P') + "ut";
- if (GenTypeBasic(type, false) != "byte" &&
- type.base_type != BASE_TYPE_BOOL) {
- setter += MakeCamel(GenTypeBasic(type, false));
- }
- return setter;
- } else {
- return "";
- }
- }
- // Returns the method name for use with add/put calls.
- std::string GenMethod(const Type &type) {
- return IsScalar(type.base_type)
- ? MakeCamel(GenTypeBasic(type, false))
- : (IsStruct(type) ? "Struct" : "Offset");
- }
- // Recursively generate arguments for a constructor, to deal with nested
- // structs.
- void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
- const char *nameprefix) {
- std::string &code = *code_ptr;
- for (auto it = struct_def.fields.vec.begin();
- it != struct_def.fields.vec.end();
- ++it) {
- auto &field = **it;
- if (IsStruct(field.value.type)) {
- // Generate arguments for a struct inside a struct. To ensure names
- // don't clash, and to make it obvious these arguments are constructing
- // a nested struct, prefix the name with the field name.
- GenStructArgs(*field.value.type.struct_def, code_ptr,
- (nameprefix + (field.name + "_")).c_str());
- } else {
- code += ", ";
- code += GenTypeBasic(DestinationType(field.value.type, false));
- code += " ";
- code += nameprefix;
- code += MakeCamel(field.name, lang_.first_camel_upper);
- }
- }
- }
- // 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,
- const char *nameprefix) {
- std::string &code = *code_ptr;
- code += " builder." + FunctionStart('P') + "rep(";
- code += NumToString(struct_def.minalign) + ", ";
- code += NumToString(struct_def.bytesize) + ");\n";
- for (auto it = struct_def.fields.vec.rbegin();
- it != struct_def.fields.vec.rend(); ++it) {
- auto &field = **it;
- if (field.padding) {
- code += " builder." + FunctionStart('P') + "ad(";
- code += NumToString(field.padding) + ");\n";
- }
- if (IsStruct(field.value.type)) {
- GenStructBody(*field.value.type.struct_def, code_ptr,
- (nameprefix + (field.name + "_")).c_str());
- } else {
- code += " builder." + FunctionStart('P') + "ut";
- code += GenMethod(field.value.type) + "(";
- code += SourceCast(field.value.type);
- auto argname = nameprefix + MakeCamel(field.name, lang_.first_camel_upper);
- code += argname;
- code += ");\n";
- }
- }
- }
- std::string GenByteBufferLength(const char *bb_name) {
- std::string bb_len = bb_name;
- if (lang_.language == IDLOptions::kCSharp) bb_len += ".Length";
- else bb_len += ".array().length";
- return bb_len;
- }
- std::string GenOffsetGetter(flatbuffers::FieldDef *key_field,
- const char *num = nullptr) {
- std::string key_offset = "";
- key_offset += lang_.accessor_prefix_static + "__offset(" +
- NumToString(key_field->value.offset) + ", ";
- if (num) {
- key_offset += num;
- key_offset += (lang_.language == IDLOptions::kCSharp ?
- ".Value, builder.DataBuffer)" : ", _bb)");
- } else {
- key_offset += GenByteBufferLength("bb");
- key_offset += " - tableOffset, bb)";
- }
- return key_offset;
- }
- std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) {
- std::string key_getter = " ";
- key_getter += "int tableOffset = " + lang_.accessor_prefix_static;
- key_getter += "__indirect(vectorLocation + 4 * (start + middle)";
- key_getter += ", bb);\n ";
- if (key_field->value.type.base_type == BASE_TYPE_STRING) {
- key_getter += "int comp = " + lang_.accessor_prefix_static;
- key_getter += FunctionStart('C') + "ompareStrings(";
- key_getter += GenOffsetGetter(key_field);
- key_getter += ", byteKey, bb);\n";
- } else {
- auto get_val = GenGetter(key_field->value.type) +
- "(" + GenOffsetGetter(key_field) + ")";
- if (lang_.language == IDLOptions::kCSharp) {
- key_getter += "int comp = " + get_val + ".CompareTo(key);\n";
- } else {
- key_getter += GenTypeGet(key_field->value.type) + " val = ";
- key_getter += get_val + ";\n";
- key_getter += " int comp = val > key ? 1 : val < key ? -1 : 0;\n";
- }
- }
- return key_getter;
- }
- std::string GenKeyGetter(flatbuffers::FieldDef *key_field) {
- std::string key_getter = "";
- auto data_buffer = (lang_.language == IDLOptions::kCSharp) ?
- "builder.DataBuffer" : "_bb";
- if (key_field->value.type.base_type == BASE_TYPE_STRING) {
- if (lang_.language == IDLOptions::kJava)
- key_getter += " return ";
- key_getter += lang_.accessor_prefix_static;
- key_getter += FunctionStart('C') + "ompareStrings(";
- key_getter += GenOffsetGetter(key_field, "o1") + ", ";
- key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")";
- if (lang_.language == IDLOptions::kJava)
- key_getter += ";";
- }
- else {
- auto field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
- "(" + GenOffsetGetter(key_field, "o1") + ")";
- if (lang_.language == IDLOptions::kCSharp) {
- key_getter += field_getter;
- field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
- "(" + GenOffsetGetter(key_field, "o2") + ")";
- key_getter += ".CompareTo(" + field_getter + ")";
- }
- else {
- key_getter += "\n " + GenTypeGet(key_field->value.type) + " val_1 = ";
- key_getter += field_getter + ";\n " + GenTypeGet(key_field->value.type);
- key_getter += " val_2 = ";
- field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
- "(" + GenOffsetGetter(key_field, "o2") + ")";
- key_getter += field_getter + ";\n";
- key_getter += " return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n ";
- }
- }
- return key_getter;
- }
- void GenStruct(StructDef &struct_def, std::string *code_ptr) {
- 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); }
- // or for tables of the form:
- // public type name() {
- // int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default;
- // }
- GenComment(struct_def.doc_comment, code_ptr, &lang_.comment_config);
- code += "public ";
- if (lang_.language == IDLOptions::kCSharp &&
- struct_def.attributes.Lookup("csharp_partial")) {
- // generate a partial class for this C# struct/table
- code += "partial ";
- } else {
- code += lang_.unsubclassable_decl;
- }
- code += lang_.accessor_type + struct_def.name;
- if (lang_.language == IDLOptions::kCSharp) {
- code += " : IFlatbufferObject";
- code += lang_.open_curly;
- code += " private ";
- code += struct_def.fixed ? "Struct" : "Table";
- code += " __p;\n";
- if (lang_.language == IDLOptions::kCSharp) {
- code += " public ByteBuffer ByteBuffer { get { return __p.bb; } }\n";
- }
- } else {
- code += lang_.inheritance_marker;
- code += struct_def.fixed ? "Struct" : "Table";
- code += lang_.open_curly;
- }
- if (!struct_def.fixed) {
- // Generate a special accessor for the table that when used as the root
- // of a FlatBuffer
- std::string method_name = FunctionStart('G') + "etRootAs" + struct_def.name;
- std::string method_signature = " public static " + struct_def.name + " " +
- 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";
- // create method that allows object reuse
- code += method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { ";
- code += lang_.set_bb_byteorder;
- code += "return (obj.__assign(_bb." + FunctionStart('G') + "etInt(_bb.";
- code += lang_.get_bb_position;
- code += ") + _bb.";
- code += lang_.get_bb_position;
- code += ", _bb)); }\n";
- if (parser_.root_struct_def_ == &struct_def) {
- if (parser_.file_identifier_.length()) {
- // Check if a buffer has the identifier.
- code += " public static ";
- code += lang_.bool_type + struct_def.name;
- code += "BufferHasIdentifier(ByteBuffer _bb) { return ";
- code += lang_.accessor_prefix_static + "__has_identifier(_bb, \"";
- code += parser_.file_identifier_;
- code += "\"); }\n";
- }
- }
- }
- // Generate the __init method that sets the field in a pre-existing
- // accessor object. This is to allow object reuse.
- code += " public void __init(int _i, ByteBuffer _bb) ";
- code += "{ " + lang_.accessor_prefix + "bb_pos = _i; ";
- code += lang_.accessor_prefix + "bb = _bb; }\n";
- code += " public " + struct_def.name + " __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, &lang_.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 = "";
- if (lang_.language == IDLOptions::kCSharp &&
- !struct_def.fixed &&
- (field.value.type.base_type == BASE_TYPE_STRUCT ||
- field.value.type.base_type == BASE_TYPE_UNION ||
- (field.value.type.base_type == BASE_TYPE_VECTOR &&
- field.value.type.element == BASE_TYPE_STRUCT))) {
- optional = lang_.optional_suffix;
- conditional_cast = "(" + type_name_dest + 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 = " public " + type_name_dest + optional + " " +
- MakeCamel(field.name, lang_.first_camel_upper);
- std::string obj = lang_.language == IDLOptions::kCSharp
- ? "(new " + type_name + "())"
- : "obj";
- // Most field accessors need to retrieve and test the field offset first,
- // this is the prefix code for that:
- auto offset_prefix = " { int o = " + lang_.accessor_prefix + "__offset(" +
- NumToString(field.value.offset) +
- "); return o != 0 ? ";
- // Generate the accessors that don't do object reuse.
- if (field.value.type.base_type == BASE_TYPE_STRUCT) {
- // Calls the accessor that takes an accessor object with a new object.
- if (lang_.language != IDLOptions::kCSharp) {
- code += method_start + "() { return ";
- code += MakeCamel(field.name, lang_.first_camel_upper);
- code += "(new ";
- code += type_name + "()); }\n";
- }
- } else if (field.value.type.base_type == BASE_TYPE_VECTOR &&
- field.value.type.element == BASE_TYPE_STRUCT) {
- // Accessors for vectors of structs also take accessor objects, this
- // generates a variant without that argument.
- if (lang_.language != IDLOptions::kCSharp) {
- code += method_start + "(int j) { return ";
- code += MakeCamel(field.name, lang_.first_camel_upper);
- code += "(new " + type_name + "(), j); }\n";
- }
- } else if (field.value.type.base_type == BASE_TYPE_UNION) {
- if (lang_.language == IDLOptions::kCSharp) {
- // Union types in C# use generic Table-derived type for better type
- // safety.
- method_start += "<TTable>";
- type_name = type_name_dest;
- }
- }
- std::string getter = dest_cast + GenGetter(field.value.type);
- code += method_start;
- std::string default_cast = "";
- // only create default casts for c# scalars or vectors of scalars
- if (lang_.language == IDLOptions::kCSharp &&
- (IsScalar(field.value.type.base_type) ||
- (field.value.type.base_type == BASE_TYPE_VECTOR &&
- IsScalar(field.value.type.element)))) {
- // For scalars, default value will be returned by GetDefaultValue().
- // If the scalar is an enum, GetDefaultValue() returns an actual c# enum
- // that doesn't need to be casted. However, default values for enum
- // elements of vectors are integer literals ("0") and are still casted
- // for clarity.
- if (field.value.type.enum_def == nullptr ||
- field.value.type.base_type == BASE_TYPE_VECTOR) {
- default_cast = "(" + type_name_dest + ")";
- }
- }
- std::string member_suffix = "; ";
- if (IsScalar(field.value.type.base_type)) {
- code += lang_.getter_prefix;
- member_suffix += lang_.getter_suffix;
- if (struct_def.fixed) {
- code += " { return " + getter;
- code += "(" + lang_.accessor_prefix + "bb_pos + ";
- code += NumToString(field.value.offset) + ")";
- code += dest_mask;
- } else {
- code += offset_prefix + getter;
- code += "(o + " + lang_.accessor_prefix + "bb_pos)" + dest_mask;
- code += " : " + default_cast;
- code += GenDefaultValue(field.value);
- }
- } else {
- switch (field.value.type.base_type) {
- case BASE_TYPE_STRUCT:
- if (lang_.language != IDLOptions::kCSharp) {
- code += "(" + type_name + " obj" + ")";
- } else {
- code += lang_.getter_prefix;
- member_suffix += lang_.getter_suffix;
- }
- if (struct_def.fixed) {
- code += " { return " + obj + ".__assign(" + lang_.accessor_prefix;
- code += "bb_pos + " + NumToString(field.value.offset) + ", ";
- code += lang_.accessor_prefix + "bb)";
- } else {
- code += offset_prefix + conditional_cast;
- code += obj + ".__assign(";
- code += field.value.type.struct_def->fixed
- ? "o + " + lang_.accessor_prefix + "bb_pos"
- : lang_.accessor_prefix + "__indirect(o + " +
- lang_.accessor_prefix + "bb_pos)";
- code += ", " + lang_.accessor_prefix + "bb) : null";
- }
- break;
- case BASE_TYPE_STRING:
- code += lang_.getter_prefix;
- member_suffix += lang_.getter_suffix;
- code += offset_prefix + getter + "(o + " + lang_.accessor_prefix;
- code += "bb_pos) : null";
- break;
- case BASE_TYPE_VECTOR: {
- auto vectortype = field.value.type.VectorType();
- code += "(";
- if (vectortype.base_type == BASE_TYPE_STRUCT) {
- if (lang_.language != IDLOptions::kCSharp)
- code += type_name + " obj, ";
- getter = obj + ".__assign";
- }
- code += "int j)" + offset_prefix + conditional_cast + getter +"(";
- auto index = lang_.accessor_prefix + "__vector(o) + j * " +
- NumToString(InlineSize(vectortype));
- if (vectortype.base_type == BASE_TYPE_STRUCT) {
- code += vectortype.struct_def->fixed
- ? index
- : lang_.accessor_prefix + "__indirect(" + index + ")";
- code += ", " + lang_.accessor_prefix + "bb";
- } else {
- code += index;
- }
- code += ")" + dest_mask + " : ";
- code += field.value.type.element == BASE_TYPE_BOOL ? "false" :
- (IsScalar(field.value.type.element) ? default_cast + "0" : "null");
- break;
- }
- case BASE_TYPE_UNION:
- if (lang_.language == IDLOptions::kCSharp) {
- code += "() where TTable : struct, IFlatbufferObject";
- code += offset_prefix + "(TTable?)" + getter;
- code += "<TTable>(o) : null";
- } else {
- code += "(" + type_name + " obj)" + offset_prefix + getter;
- code += "(obj, o) : null";
- }
- break;
- default:
- assert(0);
- }
- }
- code += member_suffix;
- code += "}\n";
- if (field.value.type.base_type == BASE_TYPE_VECTOR) {
- code += " public int " + MakeCamel(field.name, lang_.first_camel_upper);
- code += "Length";
- code += lang_.getter_prefix;
- code += offset_prefix;
- code += lang_.accessor_prefix + "__vector_len(o) : 0; ";
- code += lang_.getter_suffix;
- code += "}\n";
- }
- // Generate a ByteBuffer accessor for strings & vectors of scalars.
- if ((field.value.type.base_type == BASE_TYPE_VECTOR &&
- IsScalar(field.value.type.VectorType().base_type)) ||
- field.value.type.base_type == BASE_TYPE_STRING) {
- switch (lang_.language) {
- case IDLOptions::kJava:
- code += " public ByteBuffer ";
- code += MakeCamel(field.name, lang_.first_camel_upper);
- code += "AsByteBuffer() { return ";
- code += lang_.accessor_prefix + "__vector_as_bytebuffer(";
- code += NumToString(field.value.offset) + ", ";
- code += NumToString(field.value.type.base_type == BASE_TYPE_STRING
- ? 1
- : InlineSize(field.value.type.VectorType()));
- code += "); }\n";
- break;
- case IDLOptions::kCSharp:
- code += " public ArraySegment<byte>? Get";
- code += MakeCamel(field.name, lang_.first_camel_upper);
- code += "Bytes() { return ";
- code += lang_.accessor_prefix + "__vector_as_arraysegment(";
- code += NumToString(field.value.offset);
- code += "); }\n";
- break;
- default:
- break;
- }
- }
- // generate object accessors if is nested_flatbuffer
- auto nested = field.attributes.Lookup("nested_flatbuffer");
- if (nested) {
- auto nested_qualified_name =
- parser_.namespaces_.back()->GetFullyQualifiedName(nested->constant);
- auto nested_type = parser_.structs_.Lookup(nested_qualified_name);
- auto nested_type_name = WrapInNameSpace(*nested_type);
- auto nestedMethodName = MakeCamel(field.name, lang_.first_camel_upper)
- + "As" + nested_type_name;
- auto getNestedMethodName = nestedMethodName;
- if (lang_.language == IDLOptions::kCSharp) {
- getNestedMethodName = "Get" + nestedMethodName;
- conditional_cast = "(" + nested_type_name + lang_.optional_suffix + ")";
- }
- if (lang_.language != IDLOptions::kCSharp) {
- code += " public " + nested_type_name + lang_.optional_suffix + " ";
- code += nestedMethodName + "() { return ";
- code += getNestedMethodName + "(new " + nested_type_name + "()); }\n";
- } else {
- obj = "(new " + nested_type_name + "())";
- }
- code += " public " + nested_type_name + lang_.optional_suffix + " ";
- code += getNestedMethodName + "(";
- if (lang_.language != IDLOptions::kCSharp)
- code += nested_type_name + " obj";
- code += ") { int o = " + lang_.accessor_prefix + "__offset(";
- code += NumToString(field.value.offset) +"); ";
- code += "return o != 0 ? " + conditional_cast + obj + ".__assign(";
- code += lang_.accessor_prefix;
- code += "__indirect(" + lang_.accessor_prefix + "__vector(o)), ";
- code += lang_.accessor_prefix + "bb) : null; }\n";
- }
- // Generate mutators for scalar fields or vectors of scalars.
- if (parser_.opts.mutable_buffer) {
- auto underlying_type = field.value.type.base_type == BASE_TYPE_VECTOR
- ? field.value.type.VectorType()
- : field.value.type;
- // Boolean parameters have to be explicitly converted to byte
- // representation.
- auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
- ? "(byte)(" + field.name + " ? 1 : 0)"
- : field.name;
- auto mutator_prefix = MakeCamel("mutate", lang_.first_camel_upper);
- // A vector mutator also needs the index of the vector element it should
- // mutate.
- auto mutator_params = (field.value.type.base_type == BASE_TYPE_VECTOR
- ? "(int j, "
- : "(") + GenTypeNameDest(underlying_type) + " " + field.name + ") { ";
- auto setter_index = field.value.type.base_type == BASE_TYPE_VECTOR
- ? lang_.accessor_prefix + "__vector(o) + j * " +
- NumToString(InlineSize(underlying_type))
- : (struct_def.fixed
- ? lang_.accessor_prefix + "bb_pos + " +
- NumToString(field.value.offset)
- : "o + " + lang_.accessor_prefix + "bb_pos");
- if (IsScalar(field.value.type.base_type) ||
- (field.value.type.base_type == BASE_TYPE_VECTOR &&
- IsScalar(field.value.type.VectorType().base_type))) {
- code += " public ";
- code += struct_def.fixed ? "void " : lang_.bool_type;
- code += mutator_prefix + MakeCamel(field.name, true);
- code += mutator_params;
- if (struct_def.fixed) {
- code += GenSetter(underlying_type) + "(" + setter_index + ", ";
- code += src_cast + setter_parameter + "); }\n";
- } else {
- code += "int o = " + lang_.accessor_prefix + "__offset(";
- code += NumToString(field.value.offset) + ");";
- code += " if (o != 0) { " + GenSetter(underlying_type);
- code += "(" + setter_index + ", " + src_cast + setter_parameter +
- "); return true; } else { return false; } }\n";
- }
- }
- }
- }
- code += "\n";
- flatbuffers::FieldDef *key_field = nullptr;
- if (struct_def.fixed) {
- // create a struct constructor function
- code += " public static " + GenOffsetType(struct_def) + " ";
- code += FunctionStart('C') + "reate";
- code += struct_def.name + "(FlatBufferBuilder builder";
- GenStructArgs(struct_def, code_ptr, "");
- code += ") {\n";
- GenStructBody(struct_def, code_ptr, "");
- code += " return ";
- code += GenOffsetConstruct(struct_def,
- "builder." + std::string(lang_.get_fbb_offset));
- code += ";\n }\n";
- } else {
- // Generate a method that creates a table in one go. This is only possible
- // when the table has no struct fields, since those have to be created
- // inline, and there's no way to do so in Java.
- bool has_no_struct_fields = true;
- int num_fields = 0;
- for (auto it = struct_def.fields.vec.begin();
- it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
- if (field.deprecated) continue;
- if (IsStruct(field.value.type)) {
- has_no_struct_fields = false;
- } else {
- num_fields++;
- }
- }
- if (has_no_struct_fields && num_fields) {
- // Generate a table constructor of the form:
- // public static int createName(FlatBufferBuilder builder, args...)
- code += " public static " + GenOffsetType(struct_def) + " ";
- code += FunctionStart('C') + "reate" + struct_def.name;
- code += "(FlatBufferBuilder builder";
- for (auto it = struct_def.fields.vec.begin();
- it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
- if (field.deprecated) continue;
- code += ",\n ";
- code += GenTypeBasic(DestinationType(field.value.type, false));
- code += " ";
- code += field.name;
- if (!IsScalar(field.value.type.base_type)) code += "Offset";
- // Java doesn't have defaults, which means this method must always
- // supply all arguments, and thus won't compile when fields are added.
- if (lang_.language != IDLOptions::kJava) {
- code += " = ";
- code += GenDefaultValueBasic(field.value);
- }
- }
- code += ") {\n builder.";
- code += FunctionStart('S') + "tartObject(";
- code += NumToString(struct_def.fields.vec.size()) + ");\n";
- for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
- size;
- size /= 2) {
- for (auto it = struct_def.fields.vec.rbegin();
- it != struct_def.fields.vec.rend(); ++it) {
- auto &field = **it;
- if (!field.deprecated &&
- (!struct_def.sortbysize ||
- size == SizeOf(field.value.type.base_type))) {
- code += " " + struct_def.name + ".";
- code += FunctionStart('A') + "dd";
- code += MakeCamel(field.name) + "(builder, " + field.name;
- if (!IsScalar(field.value.type.base_type)) code += "Offset";
- code += ");\n";
- }
- }
- }
- code += " return " + struct_def.name + ".";
- code += FunctionStart('E') + "nd" + struct_def.name;
- code += "(builder);\n }\n\n";
- }
- // Generate a set of static methods that allow table construction,
- // of the form:
- // public static void addName(FlatBufferBuilder builder, short name)
- // { builder.addShort(id, name, default); }
- // Unlike the Create function, these always work.
- code += " public static void " + FunctionStart('S') + "tart";
- code += struct_def.name;
- code += "(FlatBufferBuilder builder) { builder.";
- code += FunctionStart('S') + "tartObject(";
- code += NumToString(struct_def.fields.vec.size()) + "); }\n";
- for (auto it = struct_def.fields.vec.begin();
- it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
- if (field.deprecated) continue;
- if (field.key) key_field = &field;
- code += " public static void " + FunctionStart('A') + "dd";
- code += MakeCamel(field.name);
- code += "(FlatBufferBuilder builder, ";
- code += GenTypeBasic(DestinationType(field.value.type, false));
- auto argname = MakeCamel(field.name, false);
- if (!IsScalar(field.value.type.base_type)) argname += "Offset";
- code += " " + argname + ") { builder." + FunctionStart('A') + "dd";
- code += GenMethod(field.value.type) + "(";
- code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
- code += SourceCastBasic(field.value.type);
- code += argname;
- if (!IsScalar(field.value.type.base_type) &&
- field.value.type.base_type != BASE_TYPE_UNION &&
- lang_.language == IDLOptions::kCSharp) {
- code += ".Value";
- }
- code += ", ";
- if (lang_.language == IDLOptions::kJava)
- code += SourceCastBasic( field.value.type );
- code += GenDefaultValue(field.value, false);
- code += "); }\n";
- if (field.value.type.base_type == BASE_TYPE_VECTOR) {
- auto vector_type = field.value.type.VectorType();
- auto alignment = InlineAlignment(vector_type);
- auto elem_size = InlineSize(vector_type);
- if (!IsStruct(vector_type)) {
- // Generate a method to create a vector from a Java array.
- code += " public static " + GenVectorOffsetType() + " ";
- code += FunctionStart('C') + "reate";
- code += MakeCamel(field.name);
- code += "Vector(FlatBufferBuilder builder, ";
- code += GenTypeBasic(vector_type) + "[] data) ";
- code += "{ builder." + FunctionStart('S') + "tartVector(";
- code += NumToString(elem_size);
- code += ", data." + FunctionStart('L') + "ength, ";
- code += NumToString(alignment);
- code += "); for (int i = data.";
- code += FunctionStart('L') + "ength - 1; i >= 0; i--) builder.";
- code += FunctionStart('A') + "dd";
- code += GenMethod(vector_type);
- code += "(";
- code += SourceCastBasic(vector_type, false);
- code += "data[i]";
- if (lang_.language == IDLOptions::kCSharp &&
- (vector_type.base_type == BASE_TYPE_STRUCT ||
- vector_type.base_type == BASE_TYPE_STRING))
- code += ".Value";
- code += "); return ";
- code += "builder." + FunctionStart('E') + "ndVector(); }\n";
- }
- // Generate a method to start a vector, data to be added manually after.
- code += " public static void " + FunctionStart('S') + "tart";
- code += MakeCamel(field.name);
- code += "Vector(FlatBufferBuilder builder, int numElems) ";
- code += "{ builder." + FunctionStart('S') + "tartVector(";
- code += NumToString(elem_size);
- code += ", numElems, " + NumToString(alignment);
- code += "); }\n";
- }
- }
- code += " public static " + GenOffsetType(struct_def) + " ";
- code += FunctionStart('E') + "nd" + struct_def.name;
- code += "(FlatBufferBuilder builder) {\n int o = builder.";
- code += FunctionStart('E') + "ndObject();\n";
- for (auto it = struct_def.fields.vec.begin();
- it != struct_def.fields.vec.end();
- ++it) {
- auto &field = **it;
- if (!field.deprecated && field.required) {
- code += " builder." + FunctionStart('R') + "equired(o, ";
- code += NumToString(field.value.offset);
- code += "); // " + field.name + "\n";
- }
- }
- code += " return " + GenOffsetConstruct(struct_def, "o") + ";\n }\n";
- if (parser_.root_struct_def_ == &struct_def) {
- code += " public static void ";
- code += FunctionStart('F') + "inish" + struct_def.name;
- code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def);
- code += " offset) {";
- code += " builder." + FunctionStart('F') + "inish(offset";
- if (lang_.language == IDLOptions::kCSharp) {
- code += ".Value";
- }
- if (parser_.file_identifier_.length())
- code += ", \"" + parser_.file_identifier_ + "\"";
- code += "); }\n";
- }
- }
- if (struct_def.has_key) {
- if (lang_.language == IDLOptions::kJava) {
- code += "\n @Override\n protected int keysCompare(";
- code += "Integer o1, Integer o2, ByteBuffer _bb) {";
- code += GenKeyGetter(key_field);
- code += " }\n";
- }
- else {
- code += "\n public static VectorOffset ";
- code += "CreateMySortedVectorOfTables(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 += ");\n";
- code += " return builder.CreateVectorOfTables(offsets);\n }\n";
- }
- code += "\n public static " + struct_def.name + lang_.optional_suffix;
- code += " " + FunctionStart('L') + "ookupByKey(" + GenVectorOffsetType();
- code += " vectorOffset, " + GenTypeGet(key_field->value.type);
- code += " key, ByteBuffer bb) {\n";
- if (key_field->value.type.base_type == BASE_TYPE_STRING) {
- code += " byte[] byteKey = ";
- if (lang_.language == IDLOptions::kJava)
- code += "key.getBytes(Table.UTF8_CHARSET.get());\n";
- else
- code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
- }
- code += " int vectorLocation = " + GenByteBufferLength("bb");
- code += " - vectorOffset";
- if (lang_.language == IDLOptions::kCSharp) code += ".Value";
- code += ";\n int span = ";
- code += "bb." + FunctionStart('G') + "etInt(vectorLocation);\n";
- code += " int start = 0;\n";
- code += " vectorLocation += 4;\n";
- code += " while (span != 0) {\n";
- code += " int middle = span / 2;\n";
- code += GenLookupKeyGetter(key_field);
- code += " if (comp > 0) {\n";
- code += " span = middle;\n";
- code += " } else if (comp < 0) {\n";
- code += " middle++;\n";
- code += " start += middle;\n";
- code += " span -= middle;\n";
- code += " } else {\n";
- code += " return new " + struct_def.name;
- code += "().__assign(tableOffset, bb);\n";
- code += " }\n }\n";
- code += " return null;\n";
- code += " }\n";
- }
- code += "}";
- // Java does not need the closing semi-colon on class definitions.
- code += (lang_.language != IDLOptions::kJava) ? ";" : "";
- code += "\n\n";
- }
- const LanguageParameters & lang_;
- // This tracks the current namespace used to determine if a type need to be prefixed by its namespace
- const Namespace *cur_name_space_;
- };
- } // namespace general
- bool GenerateGeneral(const Parser &parser, const std::string &path,
- const std::string &file_name) {
- general::GeneralGenerator generator(parser, path, file_name);
- return generator.generate();
- }
- std::string GeneralMakeRule(const Parser &parser, const std::string &path,
- const std::string &file_name) {
- assert(parser.opts.lang <= IDLOptions::kMAX);
- auto lang = language_parameters[parser.opts.lang];
- std::string make_rule;
- for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end();
- ++it) {
- auto &enum_def = **it;
- if (make_rule != "") make_rule += " ";
- std::string directory =
- BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace);
- make_rule += directory + enum_def.name + lang.file_extension;
- }
- for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
- ++it) {
- auto &struct_def = **it;
- if (make_rule != "") make_rule += " ";
- std::string directory =
- BaseGenerator::NamespaceDir(parser, path,
- *struct_def.defined_namespace);
- make_rule += directory + struct_def.name + lang.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 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) {
- return !parser.builder_.GetSize() ||
- flatbuffers::SaveFile(
- BinaryFileName(parser, path, file_name).c_str(),
- reinterpret_cast<char *>(parser.builder_.GetBufferPointer()),
- parser.builder_.GetSize(),
- true);
- }
- std::string BinaryMakeRule(const Parser &parser,
- const std::string &path,
- const std::string &file_name) {
- if (!parser.builder_.GetSize()) return "";
- std::string filebase = flatbuffers::StripPath(
- flatbuffers::StripExtension(file_name));
- std::string make_rule = BinaryFileName(parser, path, filebase) + ": " +
- file_name;
- auto included_files = parser.GetIncludedFilesRecursive(
- parser.root_struct_def_->file);
- for (auto it = included_files.begin();
- it != included_files.end(); ++it) {
- make_rule += " " + *it;
- }
- return make_rule;
- }
- } // namespace flatbuffers
|