#include <functional>
#include <unordered_set>
+
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#if defined(FLATBUFFERS_CPP98_STL)
-#include <cctype>
+# include <cctype>
#endif // defined(FLATBUFFERS_CPP98_STL)
namespace flatbuffers {
"POSITIVE_INFINITY",
"NEGATIVE_INFINITY");
-static const CommentConfig comment_config = {"/**", " *", " */"};
+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"};
+ "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 MakeCamel(name + "_", false);
- }
+ if (name == keywords[i]) { return MakeCamel(name + "_", false); }
}
return MakeCamel(name, false);
#KTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
- };
- return kotlin_typename[type];
+ // clang-format on
+ };
+ return kotlin_typename[type];
+ }
+ std::string GenTypePointer(const Type &type) const {
+ 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);
+ default: return "Table";
}
+ }
- std::string GenTypePointer(const Type &type) const {
- 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);
- default:
- return "Table";
- }
- }
+ std::string GenTypeGet(const Type &type) const {
+ return IsScalar(type.base_type) ? GenTypeBasic(type.base_type)
+ : GenTypePointer(type);
+ }
- std::string GenTypeGet(const Type &type) const {
- return IsScalar(type.base_type) ? GenTypeBasic(type.base_type)
- : GenTypePointer(type);
- }
+ std::string GenEnumDefaultValue(const FieldDef &field) const {
+ auto &value = field.value;
+ 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)
+ : value.constant;
+ }
- std::string GenEnumDefaultValue(const FieldDef &field) const {
- auto &value = field.value;
- 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)
- : value.constant;
+ // Generate default values to compare against a default value when
+ // `force_defaults` is `false`.
+ // Main differences are:
+ // - Floats are upcasted to doubles
+ // - Unsigned are casted to signed
+ std::string GenFBBDefaultValue(const FieldDef &field) const {
+ auto out = GenDefaultValue(field, true);
+ // All FlatBufferBuilder default floating point values are doubles
+ if (field.value.type.base_type == BASE_TYPE_FLOAT) {
+ if (out.find("Float") != std::string::npos) {
+ out.replace(0, 5, "Double");
+ }
}
+ // Guarantee all values are doubles
+ if (out.back() == 'f') out.pop_back();
+ return out;
+ }
-
- // Generate default values to compare against a default value when
- // `force_defaults` is `false`.
- // Main differences are:
- // - Floats are upcasted to doubles
- // - Unsigned are casted to signed
- std::string GenFBBDefaultValue(const FieldDef &field) const {
- auto out = GenDefaultValue(field, true);
- // All FlatBufferBuilder default floating point values are doubles
- if (field.value.type.base_type == BASE_TYPE_FLOAT) {
- if (out.find("Float") != std::string::npos) {
- out.replace(0, 5, "Double");
- }
- }
- //Guarantee all values are doubles
- if (out.back() == 'f')
- out.pop_back();
- return out;
+ // FlatBufferBuilder only store signed types, so this function
+ // returns a cast for unsigned values
+ std::string GenFBBValueCast(const FieldDef &field) const {
+ if (IsUnsigned(field.value.type.base_type)) {
+ return CastToSigned(field.value.type);
}
+ return "";
+ }
-
- // FlatBufferBuilder only store signed types, so this function
- // returns a cast for unsigned values
- std::string GenFBBValueCast(const FieldDef &field) const {
- if (IsUnsigned(field.value.type.base_type)) {
- return CastToSigned(field.value.type);
- }
- return "";
+ std::string GenDefaultValue(const FieldDef &field,
+ bool force_signed = false) const {
+ auto &value = field.value;
+ auto base_type = field.value.type.base_type;
+ if (IsFloat(base_type)) {
+ auto val = KotlinFloatGen.GenFloatConstant(field);
+ if (base_type == BASE_TYPE_DOUBLE && val.back() == 'f') {
+ val.pop_back();
+ }
+ return val;
}
- std::string GenDefaultValue(const FieldDef &field,
- bool force_signed = false) const {
- auto &value = field.value;
- auto base_type = field.value.type.base_type;
- if (IsFloat(base_type)) {
- auto val = KotlinFloatGen.GenFloatConstant(field);
- if (base_type == BASE_TYPE_DOUBLE &&
- val.back() == 'f') {
- val.pop_back();
- }
- return val;
- }
-
- if (base_type == BASE_TYPE_BOOL) {
- return value.constant == "0" ? "false" : "true";
- }
+ if (base_type == BASE_TYPE_BOOL) {
+ return value.constant == "0" ? "false" : "true";
+ }
- std::string suffix = "";
+ std::string suffix = "";
- if (base_type == BASE_TYPE_LONG || !force_signed) {
- suffix = LiteralSuffix(base_type);
- }
- return value.constant + suffix;
+ if (base_type == BASE_TYPE_LONG || !force_signed) {
+ suffix = LiteralSuffix(base_type);
}
+ return value.constant + suffix;
+ }
- void GenEnum(EnumDef &enum_def, CodeWriter &writer) const {
- if (enum_def.generated) return;
-
- GenerateComment(enum_def.doc_comment, writer, &comment_config);
-
- writer += "@Suppress(\"unused\")";
- writer += "@ExperimentalUnsignedTypes";
- writer += "class " + Esc(enum_def.name) + " private constructor() {";
- writer.IncrementIdentLevel();
-
- GenerateCompanionObject(writer, [&](){
- // Write all properties
- auto vals = enum_def.Vals();
- for (auto it = vals.begin(); it != vals.end(); ++it) {
- auto &ev = **it;
- 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("type", field_type);
- writer.SetValue("val", val + suffix);
- GenerateComment(ev.doc_comment, writer, &comment_config);
- writer += "const val {{name}}: {{type}} = {{val}}";
- }
+ void GenEnum(EnumDef &enum_def, CodeWriter &writer) const {
+ if (enum_def.generated) return;
+
+ GenerateComment(enum_def.doc_comment, writer, &comment_config);
+
+ writer += "@Suppress(\"unused\")";
+ writer += "@ExperimentalUnsignedTypes";
+ writer += "class " + Esc(enum_def.name) + " private constructor() {";
+ writer.IncrementIdentLevel();
+
+ GenerateCompanionObject(writer, [&]() {
+ // Write all properties
+ auto vals = enum_def.Vals();
+ for (auto it = vals.begin(); it != vals.end(); ++it) {
+ auto &ev = **it;
+ 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("type", field_type);
+ writer.SetValue("val", val + suffix);
+ GenerateComment(ev.doc_comment, writer, &comment_config);
+ writer += "const val {{name}}: {{type}} = {{val}}";
+ }
- // Generate a generate string table for enum values.
- // 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.Distance();
- // Average distance between values above which we consider a table
- // "too sparse". Change at will.
- static const uint64_t kMaxSparseness = 5;
- if (range / static_cast<uint64_t>(enum_def.size()) < kMaxSparseness) {
- GeneratePropertyOneLine(writer, "names", "Array<String>",
- [&](){
- writer += "arrayOf(\\";
- auto val = enum_def.Vals().front();
- for (auto it = vals.begin(); it != vals.end(); ++it) {
- auto ev = *it;
- for (auto k = enum_def.Distance(val, ev); k > 1; --k)
- writer += "\"\", \\";
- val = ev;
- writer += "\"" + (*it)->name + "\"\\";
- if (it+1 != vals.end()) {
- writer += ", \\";
- }
- }
- writer += ")";
- });
- GenerateFunOneLine(writer, "name", "e: Int", "String", [&](){
- writer += "names[e\\";
- if (enum_def.MinValue()->IsNonZero())
- writer += " - " + enum_def.MinValue()->name + ".toInt()\\";
- writer += "]";
- });
- }
+ // Generate a generate string table for enum values.
+ // 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.Distance();
+ // Average distance between values above which we consider a table
+ // "too sparse". Change at will.
+ static const uint64_t kMaxSparseness = 5;
+ if (range / static_cast<uint64_t>(enum_def.size()) < kMaxSparseness) {
+ GeneratePropertyOneLine(writer, "names", "Array<String>", [&]() {
+ writer += "arrayOf(\\";
+ auto val = enum_def.Vals().front();
+ for (auto it = vals.begin(); it != vals.end(); ++it) {
+ auto ev = *it;
+ for (auto k = enum_def.Distance(val, ev); k > 1; --k)
+ writer += "\"\", \\";
+ val = ev;
+ writer += "\"" + (*it)->name + "\"\\";
+ if (it + 1 != vals.end()) { writer += ", \\"; }
+ }
+ writer += ")";
+ });
+ GenerateFunOneLine(writer, "name", "e: Int", "String", [&]() {
+ writer += "names[e\\";
+ if (enum_def.MinValue()->IsNonZero())
+ writer += " - " + enum_def.MinValue()->name + ".toInt()\\";
+ writer += "]";
});
- writer.DecrementIdentLevel();
- writer += "}";
+ }
+ });
+ writer.DecrementIdentLevel();
+ writer += "}";
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ std::string ByteBufferGetter(const Type &type,
+ std::string bb_var_name) const {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "__string";
+ case BASE_TYPE_STRUCT: return "__struct";
+ case BASE_TYPE_UNION: return "__union";
+ case BASE_TYPE_VECTOR:
+ return ByteBufferGetter(type.VectorType(), bb_var_name);
+ case BASE_TYPE_INT:
+ case BASE_TYPE_UINT: return bb_var_name + ".getInt";
+ case BASE_TYPE_SHORT:
+ case BASE_TYPE_USHORT: return bb_var_name + ".getShort";
+ case BASE_TYPE_ULONG:
+ case BASE_TYPE_LONG: return bb_var_name + ".getLong";
+ case BASE_TYPE_FLOAT: return bb_var_name + ".getFloat";
+ case BASE_TYPE_DOUBLE: return bb_var_name + ".getDouble";
+ case BASE_TYPE_CHAR:
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_NONE:
+ 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" + MakeCamel(GenTypeBasic(type.base_type));
}
+ }
- // Returns the function name that is able to read a value of the given type.
- std::string ByteBufferGetter(const Type &type, std::string bb_var_name) const {
- switch (type.base_type) {
- case BASE_TYPE_STRING:
- return "__string";
- case BASE_TYPE_STRUCT:
- return "__struct";
- case BASE_TYPE_UNION:
- return "__union";
- case BASE_TYPE_VECTOR:
- return ByteBufferGetter(type.VectorType(), bb_var_name);
+ std::string ByteBufferSetter(const Type &type) const {
+ if (IsScalar(type.base_type)) {
+ switch (type.base_type) {
case BASE_TYPE_INT:
- case BASE_TYPE_UINT:
- return bb_var_name + ".getInt";
+ case BASE_TYPE_UINT: return "bb.putInt";
case BASE_TYPE_SHORT:
- case BASE_TYPE_USHORT:
- return bb_var_name + ".getShort";
+ case BASE_TYPE_USHORT: return "bb.putShort";
case BASE_TYPE_ULONG:
- case BASE_TYPE_LONG:
- return bb_var_name + ".getLong";
- case BASE_TYPE_FLOAT:
- return bb_var_name + ".getFloat";
- case BASE_TYPE_DOUBLE:
- return bb_var_name + ".getDouble";
+ case BASE_TYPE_LONG: return "bb.putLong";
+ case BASE_TYPE_FLOAT: return "bb.putFloat";
+ case BASE_TYPE_DOUBLE: return "bb.putDouble";
case BASE_TYPE_CHAR:
case BASE_TYPE_UCHAR:
- case BASE_TYPE_NONE:
- 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" + MakeCamel(GenTypeBasic(type.base_type));
- }
+ case BASE_TYPE_NONE:
+ case BASE_TYPE_UTYPE: return "bb.put";
+ default: return "bb.put" + MakeCamel(GenTypeBasic(type.base_type));
+ }
}
+ return "";
+ }
- std::string ByteBufferSetter(const Type &type) const {
- if (IsScalar(type.base_type)) {
- switch (type.base_type) {
- case BASE_TYPE_INT:
- case BASE_TYPE_UINT:
- return "bb.putInt";
- case BASE_TYPE_SHORT:
- case BASE_TYPE_USHORT:
- return "bb.putShort";
- case BASE_TYPE_ULONG:
- case BASE_TYPE_LONG:
- return "bb.putLong";
- case BASE_TYPE_FLOAT:
- return "bb.putFloat";
- case BASE_TYPE_DOUBLE:
- return "bb.putDouble";
- case BASE_TYPE_CHAR:
- case BASE_TYPE_UCHAR:
- case BASE_TYPE_BOOL:
- case BASE_TYPE_NONE:
- case BASE_TYPE_UTYPE:
- return "bb.put";
- default:
- return "bb.put" + MakeCamel(GenTypeBasic(type.base_type));
- }
- }
- return "";
- }
+ // Returns the function name that is able to read a value of the given type.
+ std::string GenLookupByKey(flatbuffers::FieldDef *key_field,
+ const std::string &bb_var_name,
+ const char *num = nullptr) const {
+ auto type = key_field->value.type;
+ return ByteBufferGetter(type, bb_var_name) + "(" +
+ GenOffsetGetter(key_field, num) + ")";
+ }
- // Returns the function name that is able to read a value of the given type.
- std::string GenLookupByKey(flatbuffers::FieldDef *key_field,
- const std::string &bb_var_name,
- const char *num = nullptr) const {
- auto type = key_field->value.type;
- return ByteBufferGetter(type, bb_var_name) + "(" + GenOffsetGetter(key_field, num) + ")";
+ // Returns the method name for use with add/put calls.
+ static std::string GenMethod(const Type &type) {
+ return IsScalar(type.base_type) ? ToSignedType(type)
+ : (IsStruct(type) ? "Struct" : "Offset");
+ }
+ // Recursively generate arguments for a constructor, to deal with nested
+ // structs.
+ static void GenStructArgs(const StructDef &struct_def, CodeWriter &writer,
+ const char *nameprefix) {
+ 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, writer,
+ (nameprefix + (field.name + "_")).c_str());
+ } else {
+ writer += std::string(", ") + nameprefix + "\\";
+ writer += MakeCamel(field.name) + ": \\";
+ writer += GenTypeBasic(field.value.type.base_type) + "\\";
+ }
}
+ }
- // Returns the method name for use with add/put calls.
- static std::string GenMethod(const Type &type) {
- return IsScalar(type.base_type) ? ToSignedType(type)
- : (IsStruct(type) ? "Struct" : "Offset");
+ // 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) {
+ writer.SetValue("align", NumToString(struct_def.minalign));
+ writer.SetValue("size", NumToString(struct_def.bytesize));
+ writer += "builder.prep({{align}}, {{size}})";
+ auto fields_vec = struct_def.fields.vec;
+ for (auto it = fields_vec.rbegin(); it != fields_vec.rend(); ++it) {
+ auto &field = **it;
+
+ if (field.padding) {
+ writer.SetValue("pad", NumToString(field.padding));
+ writer += "builder.pad({{pad}})";
+ }
+ if (IsStruct(field.value.type)) {
+ GenStructBody(*field.value.type.struct_def, writer,
+ (nameprefix + (field.name + "_")).c_str());
+ } else {
+ writer.SetValue("type", GenMethod(field.value.type));
+ writer.SetValue("argname", nameprefix + MakeCamel(field.name, false));
+ writer.SetValue("cast", CastToSigned(field.value.type));
+ writer += "builder.put{{type}}({{argname}}{{cast}})";
+ }
}
+ }
- // Recursively generate arguments for a constructor, to deal with nested
- // structs.
- static void GenStructArgs(const StructDef &struct_def, CodeWriter &writer,
- const char *nameprefix) {
- 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, writer,
- (nameprefix + (field.name + "_")).c_str());
- } else {
- writer += std::string(", ") + nameprefix + "\\";
- writer += MakeCamel(field.name) + ": \\";
- writer += GenTypeBasic(field.value.type.base_type) + "\\";
- }
- }
+ 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 =
+ "__offset(" + NumToString(key_field->value.offset) + ", ";
+ if (num) {
+ key_offset += num;
+ key_offset += ", _bb)";
+ } else {
+ key_offset += GenByteBufferLength("bb");
+ key_offset += " - tableOffset, bb)";
}
+ return key_offset;
+ }
- // 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) {
- writer.SetValue("align", NumToString(struct_def.minalign));
- writer.SetValue("size", NumToString(struct_def.bytesize));
- writer += "builder.prep({{align}}, {{size}})";
- auto fields_vec = struct_def.fields.vec;
- for (auto it = fields_vec.rbegin(); it != fields_vec.rend(); ++it) {
- auto &field = **it;
+ void GenStruct(StructDef &struct_def, CodeWriter &writer) const {
+ if (struct_def.generated) return;
- if (field.padding) {
- writer.SetValue("pad", NumToString(field.padding));
- writer += "builder.pad({{pad}})";
- }
- if (IsStruct(field.value.type)) {
- GenStructBody(*field.value.type.struct_def, writer,
- (nameprefix + (field.name + "_")).c_str());
- } else {
- writer.SetValue("type", GenMethod(field.value.type));
- writer.SetValue("argname", nameprefix +
- MakeCamel(field.name, false));
- writer.SetValue("cast", CastToSigned(field.value.type));
- writer += "builder.put{{type}}({{argname}}{{cast}})";
- }
- }
- }
+ GenerateComment(struct_def.doc_comment, writer, &comment_config);
+ auto fixed = struct_def.fixed;
- std::string GenByteBufferLength(const char *bb_name) const {
- std::string bb_len = bb_name;
- bb_len += ".capacity()";
- return bb_len;
- }
+ writer.SetValue("struct_name", Esc(struct_def.name));
+ writer.SetValue("superclass", fixed ? "Struct" : "Table");
- std::string GenOffsetGetter(flatbuffers::FieldDef *key_field,
- const char *num = nullptr) const {
- std::string key_offset = "__offset(" +
- NumToString(key_field->value.offset) + ", ";
- if (num) {
- key_offset += num;
- key_offset += ", _bb)";
- } else {
- key_offset += GenByteBufferLength("bb");
- key_offset += " - tableOffset, bb)";
- }
- return key_offset;
- }
+ writer += "@Suppress(\"unused\")";
+ writer += "@ExperimentalUnsignedTypes";
+ writer += "class {{struct_name}} : {{superclass}}() {\n";
- void GenStruct(StructDef &struct_def, CodeWriter &writer) const {
- if (struct_def.generated) return;
+ writer.IncrementIdentLevel();
- GenerateComment(struct_def.doc_comment, writer, &comment_config);
- auto fixed = struct_def.fixed;
+ {
+ // Generate the __init() method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ GenerateFun(writer, "__init", "_i: Int, _bb: ByteBuffer", "",
+ [&]() { writer += "__reset(_i, _bb)"; });
- writer.SetValue("struct_name", Esc(struct_def.name));
- writer.SetValue("superclass", fixed ? "Struct" : "Table");
+ // Generate assign method
+ GenerateFun(writer, "__assign", "_i: Int, _bb: ByteBuffer",
+ Esc(struct_def.name), [&]() {
+ writer += "__init(_i, _bb)";
+ writer += "return this";
+ });
- writer += "@Suppress(\"unused\")";
- writer += "@ExperimentalUnsignedTypes";
- writer += "class {{struct_name}} : {{superclass}}() {\n";
+ // Generate all getters
+ GenerateStructGetters(struct_def, writer);
- writer.IncrementIdentLevel();
+ // Generate Static Fields
+ GenerateCompanionObject(writer, [&]() {
+ if (!struct_def.fixed) {
+ FieldDef *key_field = nullptr;
- {
- // Generate the __init() method that sets the field in a pre-existing
- // accessor object. This is to allow object reuse.
- GenerateFun(writer, "__init", "_i: Int, _bb: ByteBuffer", "", [&]() {
- writer += "__reset(_i, _bb)";
- });
+ // Generate verson check method.
+ // Force compile time error if not using the same version
+ // runtime.
+ GenerateFunOneLine(writer, "validateVersion", "", "", [&]() {
+ writer += "Constants.FLATBUFFERS_1_11_1()";
+ });
- // Generate assign method
- GenerateFun(writer, "__assign", "_i: Int, _bb: ByteBuffer",
- Esc(struct_def.name), [&]() {
- writer += "__init(_i, _bb)";
- writer += "return this";
- });
+ GenerateGetRootAsAccessors(Esc(struct_def.name), writer);
+ GenerateBufferHasIdentifier(struct_def, writer);
+ GenerateTableCreator(struct_def, writer);
- // Generate all getters
- GenerateStructGetters(struct_def, writer);
+ GenerateStartStructMethod(struct_def, writer);
- // Generate Static Fields
- GenerateCompanionObject(writer, [&](){
+ // Static Add for fields
+ auto fields = struct_def.fields.vec;
+ int field_pos = -1;
+ for (auto it = fields.begin(); it != fields.end(); ++it) {
+ auto &field = **it;
+ field_pos++;
+ if (field.deprecated) continue;
+ if (field.key) key_field = &field;
+ GenerateAddField(NumToString(field_pos), field, writer);
+
+ if (field.value.type.base_type == BASE_TYPE_VECTOR) {
+ auto vector_type = field.value.type.VectorType();
+ if (!IsStruct(vector_type)) {
+ GenerateCreateVectorField(field, writer);
+ }
+ GenerateStartVectorField(field, writer);
+ }
+ }
+
+ GenerateEndStructMethod(struct_def, writer);
+ auto file_identifier = parser_.file_identifier_;
+ if (parser_.root_struct_def_ == &struct_def) {
+ GenerateFinishStructBuffer(struct_def, file_identifier, writer);
+ GenerateFinishSizePrefixed(struct_def, file_identifier, writer);
+ }
+
+ if (struct_def.has_key) {
+ GenerateLookupByKey(key_field, struct_def, writer);
+ }
+ } else {
+ GenerateStaticConstructor(struct_def, writer);
+ }
+ });
+ }
- if (!struct_def.fixed) {
- FieldDef *key_field = nullptr;
+ // class closing
+ writer.DecrementIdentLevel();
+ writer += "}";
+ }
- // Generate verson check method.
- // Force compile time error if not using the same version
- // runtime.
- GenerateFunOneLine(writer, "validateVersion", "", "", [&](){
- writer += "Constants.FLATBUFFERS_1_11_1()";
- });
+ // TODO: move key_field to reference instead of pointer
+ void GenerateLookupByKey(FieldDef *key_field, StructDef &struct_def,
+ CodeWriter &writer) const {
+ std::stringstream params;
+ params << "obj: " << Esc(struct_def.name) << "?"
+ << ", ";
+ params << "vectorLocation: Int, ";
+ params << "key: " << GenTypeGet(key_field->value.type) << ", ";
+ params << "bb: ByteBuffer";
+
+ auto statements = [&]() {
+ auto base_type = key_field->value.type.base_type;
+ writer.SetValue("struct_name", Esc(struct_def.name));
+ if (base_type == BASE_TYPE_STRING) {
+ writer +=
+ "val byteKey = key."
+ "toByteArray(Table.UTF8_CHARSET.get()!!)";
+ }
+ writer += "var span = bb.getInt(vectorLocation - 4)";
+ writer += "var start = 0";
+ writer += "while (span != 0) {";
+ writer.IncrementIdentLevel();
+ writer += "var middle = span / 2";
+ writer +=
+ "val tableOffset = __indirect(vector"
+ "Location + 4 * (start + middle), bb)";
+ if (key_field->value.type.base_type == BASE_TYPE_STRING) {
+ writer += "val comp = compareStrings(\\";
+ writer += GenOffsetGetter(key_field) + "\\";
+ writer += ", byteKey, bb)";
+ } else {
+ auto cast = CastToUsigned(key_field->value.type);
+ auto get_val = GenLookupByKey(key_field, "bb");
+ writer += "val value = " + get_val + cast;
+ writer += "val comp = value.compareTo(key)";
+ }
+ writer += "when {";
+ writer.IncrementIdentLevel();
+ writer += "comp > 0 -> span = middle";
+ writer += "comp < 0 -> {";
+ writer.IncrementIdentLevel();
+ writer += "middle++";
+ writer += "start += middle";
+ writer += "span -= middle";
+ writer.DecrementIdentLevel();
+ writer += "}"; // end comp < 0
+ writer += "else -> {";
+ writer.IncrementIdentLevel();
+ writer += "return (obj ?: {{struct_name}}()).__assign(tableOffset, bb)";
+ writer.DecrementIdentLevel();
+ writer += "}"; // end else
+ writer.DecrementIdentLevel();
+ writer += "}"; // end when
+ writer.DecrementIdentLevel();
+ writer += "}"; // end while
+ writer += "return null";
+ };
+ GenerateFun(writer, "__lookup_by_key", params.str(),
+ Esc(struct_def.name) + "?", statements);
+ }
- GenerateGetRootAsAccessors(Esc(struct_def.name), writer);
- GenerateBufferHasIdentifier(struct_def, writer);
- GenerateTableCreator(struct_def, writer);
-
- GenerateStartStructMethod(struct_def, writer);
-
- // Static Add for fields
- auto fields = struct_def.fields.vec;
- int field_pos = -1;
- for (auto it = fields.begin(); it != fields.end(); ++it) {
- auto &field = **it;
- field_pos++;
- if (field.deprecated) continue;
- if (field.key) key_field = &field;
- GenerateAddField(NumToString(field_pos), field, writer);
-
- if (field.value.type.base_type == BASE_TYPE_VECTOR) {
- auto vector_type = field.value.type.VectorType();
- if (!IsStruct(vector_type)) {
- GenerateCreateVectorField(field, writer);
- }
- GenerateStartVectorField(field, writer);
- }
- }
-
- GenerateEndStructMethod(struct_def, writer);
- auto file_identifier = parser_.file_identifier_;
- if (parser_.root_struct_def_ == &struct_def) {
- GenerateFinishStructBuffer(struct_def,
- file_identifier,
- writer);
- GenerateFinishSizePrefixed(struct_def,
- file_identifier,
- writer);
- }
-
- if (struct_def.has_key) {
- GenerateLookupByKey(key_field, struct_def, writer);
- }
- } else {
- GenerateStaticConstructor(struct_def, writer);
- }
- });
- }
+ void GenerateFinishSizePrefixed(StructDef &struct_def,
+ const std::string &identifier,
+ CodeWriter &writer) const {
+ auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : "";
+ auto params = "builder: FlatBufferBuilder, offset: Int";
+ auto method_name = "finishSizePrefixed" + Esc(struct_def.name) + "Buffer";
+ GenerateFunOneLine(writer, method_name, params, "", [&]() {
+ writer += "builder.finishSizePrefixed(offset" + id + ")";
+ });
+ }
+ void GenerateFinishStructBuffer(StructDef &struct_def,
+ const std::string &identifier,
+ CodeWriter &writer) const {
+ auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : "";
+ auto params = "builder: FlatBufferBuilder, offset: Int";
+ auto method_name = "finish" + Esc(struct_def.name) + "Buffer";
+ GenerateFunOneLine(writer, method_name, params, "",
+ [&]() { writer += "builder.finish(offset" + id + ")"; });
+ }
- // class closing
- writer.DecrementIdentLevel();
- writer += "}";
- }
+ void GenerateEndStructMethod(StructDef &struct_def,
+ CodeWriter &writer) const {
+ // Generate end{{TableName}}(builder: FlatBufferBuilder) method
+ auto name = "end" + Esc(struct_def.name);
+ auto params = "builder: FlatBufferBuilder";
+ auto returns = "Int";
+ auto field_vec = struct_def.fields.vec;
+
+ GenerateFun(writer, name, params, returns, [&]() {
+ writer += "val o = builder.endTable()";
+ writer.IncrementIdentLevel();
+ for (auto it = field_vec.begin(); it != field_vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated || !field.required) { continue; }
+ writer.SetValue("offset", NumToString(field.value.offset));
+ writer += "builder.required(o, {{offset}})";
+ }
+ writer.DecrementIdentLevel();
+ writer += "return o";
+ });
+ }
- // TODO: move key_field to reference instead of pointer
- void GenerateLookupByKey(FieldDef *key_field, StructDef &struct_def,
- CodeWriter &writer) const {
- std::stringstream params;
- params << "obj: " << Esc(struct_def.name) << "?" << ", ";
- params << "vectorLocation: Int, ";
- params << "key: " << GenTypeGet(key_field->value.type) << ", ";
- params << "bb: ByteBuffer";
-
- auto statements = [&]() {
- auto base_type = key_field->value.type.base_type;
- writer.SetValue("struct_name", Esc(struct_def.name));
- if (base_type == BASE_TYPE_STRING) {
- writer += "val byteKey = key."
- "toByteArray(Table.UTF8_CHARSET.get()!!)";
- }
- writer += "var span = bb.getInt(vectorLocation - 4)";
- writer += "var start = 0";
- writer += "while (span != 0) {";
- writer.IncrementIdentLevel();
- writer += "var middle = span / 2";
- writer += "val tableOffset = __indirect(vector"
- "Location + 4 * (start + middle), bb)";
- if (key_field->value.type.base_type == BASE_TYPE_STRING) {
- writer += "val comp = compareStrings(\\";
- writer += GenOffsetGetter(key_field) + "\\";
- writer += ", byteKey, bb)";
- } else {
- auto cast = CastToUsigned(key_field->value.type);
- auto get_val = GenLookupByKey(key_field, "bb");
- writer += "val value = " + get_val + cast;
- writer += "val comp = value.compareTo(key)";
- }
- writer += "when {";
- writer.IncrementIdentLevel();
- writer += "comp > 0 -> span = middle";
- writer += "comp < 0 -> {";
- writer.IncrementIdentLevel();
- writer += "middle++";
- writer += "start += middle";
- writer += "span -= middle";
- writer.DecrementIdentLevel();
- writer += "}"; // end comp < 0
- writer += "else -> {";
- writer.IncrementIdentLevel();
- writer += "return (obj ?: {{struct_name}}()).__assign(tableOffset, bb)";
- writer.DecrementIdentLevel();
- writer += "}"; // end else
- writer.DecrementIdentLevel();
- writer += "}"; // end when
- writer.DecrementIdentLevel();
- writer += "}"; // end while
- writer += "return null";
- };
- GenerateFun(writer, "__lookup_by_key",
- params.str(),
- Esc(struct_def.name) + "?",
- statements);
- }
+ // Generate a method to create a vector from a Kotlin array.
+ void GenerateCreateVectorField(FieldDef &field, CodeWriter &writer) const {
+ auto vector_type = field.value.type.VectorType();
+ auto method_name = "create" + MakeCamel(Esc(field.name)) + "Vector";
+ auto params = "builder: FlatBufferBuilder, data: " +
+ GenTypeBasic(vector_type.base_type) + "Array";
+ writer.SetValue("size", NumToString(InlineSize(vector_type)));
+ writer.SetValue("align", NumToString(InlineAlignment(vector_type)));
+ writer.SetValue("root", GenMethod(vector_type));
+ writer.SetValue("cast", CastToSigned(vector_type));
+
+ GenerateFun(writer, method_name, params, "Int", [&]() {
+ writer += "builder.startVector({{size}}, data.size, {{align}})";
+ writer += "for (i in data.size - 1 downTo 0) {";
+ writer.IncrementIdentLevel();
+ writer += "builder.add{{root}}(data[i]{{cast}})";
+ writer.DecrementIdentLevel();
+ writer += "}";
+ writer += "return builder.endVector()";
+ });
+ }
- void GenerateFinishSizePrefixed(StructDef &struct_def,
- const std::string &identifier,
- CodeWriter &writer) const {
- auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : "";
- auto params = "builder: FlatBufferBuilder, offset: Int";
- auto method_name = "finishSizePrefixed" + Esc(struct_def.name) + "Buffer";
- GenerateFunOneLine(writer, method_name, params, "", [&]() {
- writer += "builder.finishSizePrefixed(offset" + id + ")";
- });
- }
- void GenerateFinishStructBuffer(StructDef &struct_def,
- const std::string &identifier,
- CodeWriter &writer) const {
- auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : "";
- auto params = "builder: FlatBufferBuilder, offset: Int";
- auto method_name = "finish" + Esc(struct_def.name) + "Buffer";
- GenerateFunOneLine(writer, method_name, params, "", [&]() {
- writer += "builder.finish(offset" + id + ")";
+ void GenerateStartVectorField(FieldDef &field, CodeWriter &writer) const {
+ // Generate a method to start a vector, data to be added manually
+ // after.
+ auto vector_type = field.value.type.VectorType();
+ auto params = "builder: FlatBufferBuilder, numElems: Int";
+ writer.SetValue("size", NumToString(InlineSize(vector_type)));
+ writer.SetValue("align", NumToString(InlineAlignment(vector_type)));
+
+ GenerateFunOneLine(
+ writer, "start" + MakeCamel(Esc(field.name) + "Vector", true), params,
+ "", [&]() {
+ writer += "builder.startVector({{size}}, numElems, {{align}})";
});
- }
+ }
- void GenerateEndStructMethod(StructDef &struct_def, CodeWriter &writer) const {
- // Generate end{{TableName}}(builder: FlatBufferBuilder) method
- auto name = "end" + Esc(struct_def.name);
- auto params = "builder: FlatBufferBuilder";
- auto returns = "Int";
- auto field_vec = struct_def.fields.vec;
-
- GenerateFun(writer, name, params, returns, [&](){
- writer += "val o = builder.endTable()";
- writer.IncrementIdentLevel();
- for (auto it = field_vec.begin(); it != field_vec.end(); ++it) {
- auto &field = **it;
- if (field.deprecated || !field.required) {
- continue;
- }
- writer.SetValue("offset", NumToString(field.value.offset));
- writer += "builder.required(o, {{offset}})";
- }
- writer.DecrementIdentLevel();
- writer += "return o";
- });
- }
+ void GenerateAddField(std::string field_pos, FieldDef &field,
+ CodeWriter &writer) const {
+ auto field_type = GenTypeBasic(field.value.type.base_type);
+ auto secondArg = MakeCamel(Esc(field.name), false) + ": " + field_type;
+ GenerateFunOneLine(writer, "add" + MakeCamel(Esc(field.name), true),
+ "builder: FlatBufferBuilder, " + secondArg, "", [&]() {
+ auto method = GenMethod(field.value.type);
+ writer.SetValue("field_name",
+ MakeCamel(Esc(field.name), false));
+ 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}})";
+ });
+ }
- // Generate a method to create a vector from a Kotlin array.
- void GenerateCreateVectorField(FieldDef &field, CodeWriter &writer) const {
- auto vector_type = field.value.type.VectorType();
- auto method_name = "create" + MakeCamel(Esc(field.name)) + "Vector";
- auto params = "builder: FlatBufferBuilder, data: " +
- GenTypeBasic(vector_type.base_type) + "Array";
- writer.SetValue("size", NumToString(InlineSize(vector_type)));
- writer.SetValue("align", NumToString(InlineAlignment(vector_type)));
- writer.SetValue("root", GenMethod(vector_type));
- writer.SetValue("cast", CastToSigned(vector_type));
-
- GenerateFun(writer, method_name, params, "Int", [&](){
- writer += "builder.startVector({{size}}, data.size, {{align}})";
- writer += "for (i in data.size - 1 downTo 0) {";
- writer.IncrementIdentLevel();
- writer += "builder.add{{root}}(data[i]{{cast}})";
- writer.DecrementIdentLevel();
- writer += "}";
- writer += "return builder.endVector()";
- });
+ static std::string ToSignedType(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_UINT: return GenTypeBasic(BASE_TYPE_INT);
+ case BASE_TYPE_ULONG: return GenTypeBasic(BASE_TYPE_LONG);
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_NONE:
+ case BASE_TYPE_UTYPE: return GenTypeBasic(BASE_TYPE_CHAR);
+ case BASE_TYPE_USHORT: return GenTypeBasic(BASE_TYPE_SHORT);
+ case BASE_TYPE_VECTOR: return ToSignedType(type.VectorType());
+ default: return GenTypeBasic(type.base_type);
}
+ }
- void GenerateStartVectorField(FieldDef &field, CodeWriter &writer) const {
- // Generate a method to start a vector, data to be added manually
- // after.
- auto vector_type = field.value.type.VectorType();
- auto params = "builder: FlatBufferBuilder, numElems: Int";
- writer.SetValue("size", NumToString(InlineSize(vector_type)));
- writer.SetValue("align", NumToString(InlineAlignment(vector_type)));
-
- GenerateFunOneLine(writer,
- "start" + MakeCamel(Esc(field.name) + "Vector", true),
- params,
- "",
- [&]() {
- writer += "builder.startVector({{size}}, numElems, {{align}})";
- });
- }
+ static std::string FlexBufferBuilderCast(const std::string &method,
+ FieldDef &field, bool isFirst) {
+ auto field_type = GenTypeBasic(field.value.type.base_type);
+ std::string to_type;
+ if (method == "Boolean")
+ to_type = "Boolean";
+ else if (method == "Long")
+ to_type = "Long";
+ else if (method == "Int" || method == "Offset" || method == "Struct")
+ to_type = "Int";
+ else if (method == "Byte" || method.empty())
+ to_type = isFirst ? "Byte" : "Int";
+ else if (method == "Short")
+ to_type = isFirst ? "Short" : "Int";
+ else if (method == "Double")
+ to_type = "Double";
+ else if (method == "Float")
+ to_type = isFirst ? "Float" : "Double";
+ else if (method == "UByte")
+
+ if (field_type != to_type) return ".to" + to_type + "()";
+ return "";
+ }
- void GenerateAddField(std::string field_pos, FieldDef &field,
- CodeWriter &writer) const {
- auto field_type = GenTypeBasic(field.value.type.base_type);
- auto secondArg = MakeCamel(Esc(field.name), false) + ": " + field_type;
- GenerateFunOneLine(writer, "add" + MakeCamel(Esc(field.name), true),
- "builder: FlatBufferBuilder, " + secondArg, "", [&](){
- auto method = GenMethod(field.value.type);
- writer.SetValue("field_name", MakeCamel(Esc(field.name), false));
- 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}})";
- });
- }
+ // fun startMonster(builder: FlatBufferBuilder) = builder.startTable(11)
+ void GenerateStartStructMethod(StructDef &struct_def,
+ CodeWriter &code) const {
+ GenerateFunOneLine(code, "start" + Esc(struct_def.name),
+ "builder: FlatBufferBuilder", "", [&]() {
+ code += "builder.startTable(" +
+ NumToString(struct_def.fields.vec.size()) +
+ ")";
+ });
+ }
- static std::string ToSignedType(const Type & type) {
- switch(type.base_type) {
- case BASE_TYPE_UINT:
- return GenTypeBasic(BASE_TYPE_INT);
- case BASE_TYPE_ULONG:
- return GenTypeBasic(BASE_TYPE_LONG);
- case BASE_TYPE_UCHAR:
- case BASE_TYPE_NONE:
- case BASE_TYPE_UTYPE:
- return GenTypeBasic(BASE_TYPE_CHAR);
- case BASE_TYPE_USHORT:
- return GenTypeBasic(BASE_TYPE_SHORT);
- case BASE_TYPE_VECTOR:
- return ToSignedType(type.VectorType());
- default:
- return GenTypeBasic(type.base_type);
- }
+ void GenerateTableCreator(StructDef &struct_def, CodeWriter &writer) const {
+ // 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;
+ auto fields_vec = struct_def.fields.vec;
+
+ for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ if (IsStruct(field.value.type)) {
+ has_no_struct_fields = false;
+ } else {
+ num_fields++;
+ }
}
+ // JVM specifications restrict default constructor params to be < 255.
+ // Longs and doubles take up 2 units, so we set the limit to be < 127.
+ if (has_no_struct_fields && num_fields && num_fields < 127) {
+ // Generate a table constructor of the form:
+ // public static int createName(FlatBufferBuilder builder, args...)
+
+ auto name = "create" + Esc(struct_def.name);
+ 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 << ", " << MakeCamel(Esc(field.name), false);
+ if (!IsScalar(field.value.type.base_type)) {
+ params << "Offset: ";
+ } else {
+ params << ": ";
+ }
+ params << GenTypeBasic(field.value.type.base_type);
+ }
- static std::string FlexBufferBuilderCast(const std::string &method,
- FieldDef &field,
- bool isFirst) {
- auto field_type = GenTypeBasic(field.value.type.base_type);
- std::string to_type;
- if (method == "Boolean")
- to_type = "Boolean";
- else if (method == "Long")
- to_type = "Long";
- else if (method == "Int" || method == "Offset" || method == "Struct")
- to_type = "Int";
- else if (method == "Byte" || method.empty())
- to_type = isFirst ? "Byte" : "Int";
- else if (method == "Short")
- to_type = isFirst ? "Short" : "Int";
- else if (method == "Double")
- to_type = "Double";
- else if (method == "Float")
- to_type = isFirst ? "Float" : "Double";
- else if (method == "UByte")
-
- if (field_type != to_type)
- return ".to" + to_type + "()";
- return "";
- }
+ GenerateFun(writer, name, params.str(), "Int", [&]() {
+ writer.SetValue("vec_size", NumToString(fields_vec.size()));
- // fun startMonster(builder: FlatBufferBuilder) = builder.startTable(11)
- void GenerateStartStructMethod(StructDef &struct_def, CodeWriter &code) const {
- GenerateFunOneLine(code, "start" + Esc(struct_def.name),
- "builder: FlatBufferBuilder", "", [&] () {
- code += "builder.startTable("+ NumToString(struct_def.fields.vec.size()) + ")";
- });
+ writer += "builder.startTable({{vec_size}})";
+
+ auto sortbysize = struct_def.sortbysize;
+ auto largest = sortbysize ? sizeof(largest_scalar_t) : 1;
+ for (size_t size = largest; size; size /= 2) {
+ for (auto it = fields_vec.rbegin(); it != fields_vec.rend(); ++it) {
+ auto &field = **it;
+ auto base_type_size = SizeOf(field.value.type.base_type);
+ if (!field.deprecated && (!sortbysize || size == base_type_size)) {
+ writer.SetValue("camel_field_name",
+ MakeCamel(Esc(field.name), true));
+ writer.SetValue("field_name", MakeCamel(Esc(field.name), false));
+
+ writer += "add{{camel_field_name}}(builder, {{field_name}}\\";
+ if (!IsScalar(field.value.type.base_type)) {
+ writer += "Offset\\";
+ }
+ writer += ")";
+ }
+ }
+ }
+ writer += "return end{{struct_name}}(builder)";
+ });
}
+ }
+ void GenerateBufferHasIdentifier(StructDef &struct_def,
+ CodeWriter &writer) const {
+ auto file_identifier = parser_.file_identifier_;
+ // Check if a buffer has the identifier.
+ if (parser_.root_struct_def_ != &struct_def || !file_identifier.length())
+ return;
+ auto name = MakeCamel(Esc(struct_def.name), false);
+ GenerateFunOneLine(writer, name + "BufferHasIdentifier", "_bb: ByteBuffer",
+ "Boolean", [&]() {
+ writer += "__has_identifier(_bb, \"" +
+ file_identifier + "\")";
+ });
+ }
- void GenerateTableCreator(StructDef &struct_def, CodeWriter &writer) const {
- // 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;
- auto fields_vec = struct_def.fields.vec;
+ void GenerateStructGetters(StructDef &struct_def, CodeWriter &writer) const {
+ auto fields_vec = struct_def.fields.vec;
+ FieldDef *key_field = nullptr;
+ for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ if (field.key) key_field = &field;
+
+ GenerateComment(field.doc_comment, writer, &comment_config);
+
+ auto field_name = MakeCamel(Esc(field.name), false);
+ auto field_type = GenTypeGet(field.value.type);
+ auto field_default_value = GenDefaultValue(field);
+ auto return_type = GenTypeGet(field.value.type);
+ auto bbgetter = ByteBufferGetter(field.value.type, "bb");
+ auto ucast = CastToUsigned(field);
+ auto offset_val = NumToString(field.value.offset);
+ auto offset_prefix =
+ "val o = __offset(" + offset_val + "); return o != 0 ? ";
+ auto value_base_type = field.value.type.base_type;
+ // Most field accessors need to retrieve and test the field offset
+ // first, this is the offset value for that:
+ writer.SetValue("offset", NumToString(field.value.offset));
+ writer.SetValue("return_type", return_type);
+ writer.SetValue("field_type", field_type);
+ writer.SetValue("field_name", field_name);
+ writer.SetValue("field_default", field_default_value);
+ writer.SetValue("bbgetter", bbgetter);
+ writer.SetValue("ucast", ucast);
+
+ auto opt_ret_type = return_type + "?";
+ // Generate the accessors that don't do object reuse.
+ if (value_base_type == BASE_TYPE_STRUCT) {
+ // Calls the accessor that takes an accessor object with a
+ // new object.
+ // val pos
+ // get() = pos(Vec3())
+ GenerateGetterOneLine(writer, field_name, opt_ret_type, [&]() {
+ writer += "{{field_name}}({{field_type}}())";
+ });
+ } else if (value_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.
+ // ex: fun weapons(j: Int) = weapons(Weapon(), j)
+ GenerateFunOneLine(writer, field_name, "j: Int", opt_ret_type, [&]() {
+ writer += "{{field_name}}({{return_type}}(), j)";
+ });
+ }
- for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) {
- auto &field = **it;
- if (field.deprecated) continue;
- if (IsStruct(field.value.type)) {
- has_no_struct_fields = false;
+ if (IsScalar(value_base_type)) {
+ if (struct_def.fixed) {
+ GenerateGetterOneLine(writer, field_name, return_type, [&]() {
+ writer += "{{bbgetter}}(bb_pos + {{offset}}){{ucast}}";
+ });
+ } else {
+ GenerateGetter(writer, field_name, return_type, [&]() {
+ writer += "val o = __offset({{offset}})";
+ writer +=
+ "return if(o != 0) {{bbgetter}}"
+ "(o + bb_pos){{ucast}} else "
+ "{{field_default}}";
+ });
+ }
+ } else {
+ switch (value_base_type) {
+ case BASE_TYPE_STRUCT:
+ if (struct_def.fixed) {
+ // create getter with object reuse
+ // ex:
+ // fun pos(obj: Vec3) : Vec3? = obj.__assign(bb_pos + 4, bb)
+ // ? adds nullability annotation
+ GenerateFunOneLine(
+ writer, field_name, "obj: " + field_type, return_type + "?",
+ [&]() { writer += "obj.__assign(bb_pos + {{offset}}, bb)"; });
} else {
- num_fields++;
+ // create getter with object reuse
+ // ex:
+ // fun pos(obj: Vec3) : Vec3? {
+ // val o = __offset(4)
+ // return if(o != 0) {
+ // obj.__assign(o + bb_pos, bb)
+ // else {
+ // null
+ // }
+ // }
+ // ? adds nullability annotation
+ GenerateFun(
+ writer, field_name, "obj: " + field_type, return_type + "?",
+ [&]() {
+ auto fixed = field.value.type.struct_def->fixed;
+
+ writer.SetValue("seek", Indirect("o + bb_pos", fixed));
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() { writer += "obj.__assign({{seek}}, bb)"; },
+ [&]() { writer += "null"; });
+ });
}
- }
- // JVM specifications restrict default constructor params to be < 255.
- // Longs and doubles take up 2 units, so we set the limit to be < 127.
- if (has_no_struct_fields && num_fields && num_fields < 127) {
- // Generate a table constructor of the form:
- // public static int createName(FlatBufferBuilder builder, args...)
-
- auto name = "create" + Esc(struct_def.name);
- 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 << ", " << MakeCamel(Esc(field.name), false);
- if (!IsScalar(field.value.type.base_type)){
- params << "Offset: ";
- } else {
- params << ": ";
- }
- params << GenTypeBasic(field.value.type.base_type);
+ break;
+ case BASE_TYPE_STRING:
+ // create string getter
+ // e.g.
+ // val Name : String?
+ // get() = {
+ // val o = __offset(10)
+ // return if (o != 0) __string(o + bb_pos) else null
+ // }
+ // ? adds nullability annotation
+ GenerateGetter(writer, field_name, return_type + "?", [&]() {
+ writer += "val o = __offset({{offset}})";
+ writer += "return if (o != 0) __string(o + bb_pos) else null";
+ });
+ break;
+ case BASE_TYPE_VECTOR: {
+ // e.g.
+ // fun inventory(j: Int) : UByte {
+ // val o = __offset(14)
+ // return if (o != 0) {
+ // bb.get(__vector(o) + j * 1).toUByte()
+ // } else {
+ // 0
+ // }
+ // }
+
+ auto vectortype = field.value.type.VectorType();
+ std::string params = "j: Int";
+ std::string nullable = IsScalar(vectortype.base_type) ? "" : "?";
+
+ if (vectortype.base_type == BASE_TYPE_STRUCT ||
+ vectortype.base_type == BASE_TYPE_UNION) {
+ params = "obj: " + field_type + ", j: Int";
}
- GenerateFun(writer, name, params.str(), "Int", [&]() {
- writer.SetValue("vec_size", NumToString(fields_vec.size()));
-
- writer += "builder.startTable({{vec_size}})";
-
- auto sortbysize = struct_def.sortbysize;
- auto largest = sortbysize ? sizeof(largest_scalar_t) : 1;
- for (size_t size = largest; size; size /= 2) {
- for (auto it = fields_vec.rbegin(); it != fields_vec.rend();
- ++it) {
- auto &field = **it;
- auto base_type_size = SizeOf(field.value.type.base_type);
- if (!field.deprecated &&
- (!sortbysize || size == base_type_size)) {
- writer.SetValue("camel_field_name",
- MakeCamel(Esc(field.name), true));
- writer.SetValue("field_name",
- MakeCamel(Esc(field.name), false));
-
- writer += "add{{camel_field_name}}(builder, {{field_name}}\\";
- if (!IsScalar(field.value.type.base_type)){
- writer += "Offset\\";
- }
- writer += ")";
- }
- }
+ auto ret_type = return_type + nullable;
+ GenerateFun(writer, field_name, params, ret_type, [&]() {
+ auto inline_size = NumToString(InlineSize(vectortype));
+ auto index = "__vector(o) + j * " + inline_size;
+ auto not_found = NotFoundReturn(field.value.type.element);
+ auto found = "";
+ writer.SetValue("index", index);
+ switch (vectortype.base_type) {
+ case BASE_TYPE_STRUCT: {
+ bool fixed = vectortype.struct_def->fixed;
+ writer.SetValue("index", Indirect(index, fixed));
+ found = "obj.__assign({{index}}, bb)";
+ break;
}
- writer += "return end{{struct_name}}(builder)";
+ case BASE_TYPE_UNION:
+ found = "{{bbgetter}}(obj, {{index}} - bb_pos){{ucast}}";
+ break;
+ default: found = "{{bbgetter}}({{index}}){{ucast}}";
+ }
+ OffsetWrapper(
+ writer, offset_val, [&]() { writer += found; },
+ [&]() { writer += not_found; });
});
+ break;
+ }
+ case BASE_TYPE_UNION:
+ GenerateFun(writer, field_name, "obj: " + field_type,
+ return_type + "?", [&]() {
+ writer += OffsetWrapperOneLine(
+ offset_val, bbgetter + "(obj, o + bb_pos)",
+ "null");
+ });
+ break;
+ default: FLATBUFFERS_ASSERT(0);
}
+ }
- }
- void GenerateBufferHasIdentifier(StructDef &struct_def,
- CodeWriter &writer) const {
- auto file_identifier = parser_.file_identifier_;
- // Check if a buffer has the identifier.
- if (parser_.root_struct_def_ != &struct_def || !file_identifier.length())
- return;
- auto name = MakeCamel(Esc(struct_def.name), false);
- GenerateFunOneLine(writer, name + "BufferHasIdentifier",
- "_bb: ByteBuffer",
- "Boolean",
- [&]() {
- writer += "__has_identifier(_bb, \"" + file_identifier + "\")";
+ if (value_base_type == BASE_TYPE_VECTOR) {
+ // Generate Lenght functions for vectors
+ GenerateGetter(writer, field_name + "Length", "Int", [&]() {
+ writer += OffsetWrapperOneLine(offset_val, "__vector_len(o)", "0");
});
- }
-
- void GenerateStructGetters(StructDef &struct_def, CodeWriter &writer) const {
- auto fields_vec = struct_def.fields.vec;
- FieldDef *key_field = nullptr;
- for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) {
- auto &field = **it;
- if (field.deprecated) continue;
- if (field.key) key_field = &field;
- GenerateComment(field.doc_comment, writer, &comment_config);
-
- auto field_name = MakeCamel(Esc(field.name), false);
- auto field_type = GenTypeGet(field.value.type);
- auto field_default_value = GenDefaultValue(field);
- auto return_type = GenTypeGet(field.value.type);
- auto bbgetter = ByteBufferGetter(field.value.type, "bb");
- auto ucast = CastToUsigned(field);
- auto offset_val = NumToString(field.value.offset);
- auto offset_prefix = "val o = __offset(" + offset_val
- + "); return o != 0 ? ";
- auto value_base_type = field.value.type.base_type;
- // Most field accessors need to retrieve and test the field offset
- // first, this is the offset value for that:
- writer.SetValue("offset", NumToString(field.value.offset));
- writer.SetValue("return_type", return_type);
- writer.SetValue("field_type", field_type);
- writer.SetValue("field_name", field_name);
- writer.SetValue("field_default", field_default_value);
- writer.SetValue("bbgetter", bbgetter);
- writer.SetValue("ucast", ucast);
-
- auto opt_ret_type = return_type + "?";
- // Generate the accessors that don't do object reuse.
- if (value_base_type == BASE_TYPE_STRUCT) {
- // Calls the accessor that takes an accessor object with a
- // new object.
- // val pos
- // get() = pos(Vec3())
- GenerateGetterOneLine(writer, field_name, opt_ret_type, [&](){
- writer += "{{field_name}}({{field_type}}())";
- });
- } else if (value_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.
- // ex: fun weapons(j: Int) = weapons(Weapon(), j)
- GenerateFunOneLine(writer, field_name, "j: Int", opt_ret_type, [&](){
- writer += "{{field_name}}({{return_type}}(), j)";
- });
+ // See if we should generate a by-key accessor.
+ if (field.value.type.element == BASE_TYPE_STRUCT &&
+ !field.value.type.struct_def->fixed) {
+ auto &sd = *field.value.type.struct_def;
+ auto &fields = sd.fields.vec;
+ for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
+ auto &kfield = **kit;
+ if (kfield.key) {
+ auto qualified_name = WrapInNameSpace(sd);
+ auto name = MakeCamel(Esc(field.name), false) + "ByKey";
+ auto params = "key: " + GenTypeGet(kfield.value.type);
+ auto rtype = qualified_name + "?";
+ GenerateFun(writer, name, params, rtype, [&]() {
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() {
+ writer += qualified_name +
+ ".__lookup_by_key(null, __vector(o), key, bb)";
+ },
+ [&]() { writer += "null"; });
+ });
+
+ auto param2 = "obj: " + qualified_name +
+ ", key: " + GenTypeGet(kfield.value.type);
+ GenerateFun(writer, name, param2, rtype, [&]() {
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() {
+ writer += qualified_name +
+ ".__lookup_by_key(obj, __vector(o), key, bb)";
+ },
+ [&]() { writer += "null"; });
+ });
+
+ break;
}
+ }
+ }
+ }
- if (IsScalar(value_base_type)) {
- if (struct_def.fixed) {
- GenerateGetterOneLine(writer, field_name, return_type, [&](){
- writer += "{{bbgetter}}(bb_pos + {{offset}}){{ucast}}";
- });
- } else {
- GenerateGetter(writer, field_name, return_type, [&](){
- writer += "val o = __offset({{offset}})";
- writer += "return if(o != 0) {{bbgetter}}"
- "(o + bb_pos){{ucast}} else "
- "{{field_default}}";
- });
- }
- } else {
- switch (value_base_type) {
- case BASE_TYPE_STRUCT:
- if (struct_def.fixed) {
- // create getter with object reuse
- // ex:
- // fun pos(obj: Vec3) : Vec3? = obj.__assign(bb_pos + 4, bb)
- // ? adds nullability annotation
- GenerateFunOneLine(writer,
- field_name, "obj: " + field_type ,
- return_type + "?", [&](){
- writer += "obj.__assign(bb_pos + {{offset}}, bb)";
- });
- } else {
- // create getter with object reuse
- // ex:
- // fun pos(obj: Vec3) : Vec3? {
- // val o = __offset(4)
- // return if(o != 0) {
- // obj.__assign(o + bb_pos, bb)
- // else {
- // null
- // }
- // }
- // ? adds nullability annotation
- GenerateFun(writer, field_name, "obj: " + field_type,
- return_type + "?", [&](){
- auto fixed = field.value.type.struct_def->fixed;
-
- writer.SetValue("seek", Indirect("o + bb_pos", fixed));
- OffsetWrapper(writer,
- offset_val,
- [&]() { writer += "obj.__assign({{seek}}, bb)"; },
- [&]() { writer += "null"; });
- });
- }
- break;
- case BASE_TYPE_STRING:
- // create string getter
- // e.g.
- // val Name : String?
- // get() = {
- // val o = __offset(10)
- // return if (o != 0) __string(o + bb_pos) else null
- // }
- // ? adds nullability annotation
- GenerateGetter(writer, field_name, return_type + "?", [&](){
-
- writer += "val o = __offset({{offset}})";
- writer += "return if (o != 0) __string(o + bb_pos) else null";
- });
- break;
- case BASE_TYPE_VECTOR: {
- // e.g.
- // fun inventory(j: Int) : UByte {
- // val o = __offset(14)
- // return if (o != 0) {
- // bb.get(__vector(o) + j * 1).toUByte()
- // } else {
- // 0
- // }
- // }
-
- auto vectortype = field.value.type.VectorType();
- std::string params = "j: Int";
- std::string nullable = IsScalar(vectortype.base_type) ? ""
- : "?";
-
- if (vectortype.base_type == BASE_TYPE_STRUCT ||
- vectortype.base_type == BASE_TYPE_UNION) {
- params = "obj: " + field_type + ", j: Int";
- }
-
-
- writer.SetValue("toType", "YYYYY");
-
- auto ret_type = return_type + nullable;
- GenerateFun(writer, field_name, params, ret_type, [&](){
- auto inline_size = NumToString(InlineSize(vectortype));
- auto index = "__vector(o) + j * " + inline_size;
- auto not_found = NotFoundReturn(field.value.type.element);
- auto found = "";
- writer.SetValue("index", index);
- switch(vectortype.base_type) {
- case BASE_TYPE_STRUCT: {
- bool fixed = vectortype.struct_def->fixed;
- writer.SetValue("index", Indirect(index, fixed));
- found = "obj.__assign({{index}}, bb)";
- break;
- }
- case BASE_TYPE_UNION:
- found = "{{bbgetter}}(obj, {{index}} - bb_pos){{ucast}}";
- break;
- default:
- found = "{{bbgetter}}({{index}}){{ucast}}";
- }
- OffsetWrapper(writer, offset_val,
- [&]() { writer += found; } ,
- [&]() { writer += not_found; });
- });
- break;
- }
- case BASE_TYPE_UNION:
- GenerateFun(writer, field_name, "obj: " + field_type,
- return_type + "?", [&](){
- writer += OffsetWrapperOneLine(offset_val,
- bbgetter + "(obj, o)",
- "null");
- });
- break;
- default:
- FLATBUFFERS_ASSERT(0);
- }
- }
+ if ((value_base_type == BASE_TYPE_VECTOR &&
+ IsScalar(field.value.type.VectorType().base_type)) ||
+ value_base_type == BASE_TYPE_STRING) {
+ auto end_idx =
+ NumToString(value_base_type == BASE_TYPE_STRING
+ ? 1
+ : InlineSize(field.value.type.VectorType()));
+ // Generate a ByteBuffer accessor for strings & vectors of scalars.
+ // e.g.
+ // val inventoryByteBuffer: ByteBuffer
+ // get = __vector_as_bytebuffer(14, 1)
+
+ GenerateGetterOneLine(
+ writer, field_name + "AsByteBuffer", "ByteBuffer", [&]() {
+ writer.SetValue("end", end_idx);
+ writer += "__vector_as_bytebuffer({{offset}}, {{end}})";
+ });
- if (value_base_type == BASE_TYPE_VECTOR) {
- // Generate Lenght functions for vectors
- GenerateGetter(writer, field_name + "Length", "Int", [&](){
- writer += OffsetWrapperOneLine(offset_val,
- "__vector_len(o)", "0");
- });
-
- // See if we should generate a by-key accessor.
- if (field.value.type.element == BASE_TYPE_STRUCT &&
- !field.value.type.struct_def->fixed) {
- auto &sd = *field.value.type.struct_def;
- auto &fields = sd.fields.vec;
- for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
- auto &kfield = **kit;
- if (kfield.key) {
- auto qualified_name = WrapInNameSpace(sd);
- auto name = MakeCamel(Esc(field.name), false) + "ByKey";
- auto params = "key: " + GenTypeGet(kfield.value.type);
- auto rtype = qualified_name + "?";
- GenerateFun(writer, name, params, rtype, [&] () {
- OffsetWrapper(writer, offset_val,
- [&] () {
- writer += qualified_name +
- ".__lookup_by_key(null, __vector(o), key, bb)";
- },
- [&] () {
- writer += "null";
- });
- });
-
- auto param2 = "obj: " + qualified_name +
- ", key: " +
- GenTypeGet(kfield.value.type);
- GenerateFun(writer, name, param2, rtype, [&](){
- OffsetWrapper(writer, offset_val,
- [&] () {
- writer += qualified_name +
- ".__lookup_by_key(obj, __vector(o), key, bb)";
- },
- [&]() { writer += "null"; });
- });
-
- break;
- }
- }
- }
- }
+ // Generate a ByteBuffer accessor for strings & vectors of scalars.
+ // e.g.
+ // fun inventoryInByteBuffer(_bb: Bytebuffer):
+ // ByteBuffer = __vector_as_bytebuffer(_bb, 14, 1)
+ GenerateFunOneLine(
+ writer, field_name + "InByteBuffer", "_bb: ByteBuffer",
+ "ByteBuffer", [&]() {
+ writer.SetValue("end", end_idx);
+ writer += "__vector_in_bytebuffer(_bb, {{offset}}, {{end}})";
+ });
+ }
- if ((value_base_type == BASE_TYPE_VECTOR &&
- IsScalar(field.value.type.VectorType().base_type)) ||
- value_base_type == BASE_TYPE_STRING) {
-
- auto end_idx = NumToString(value_base_type == BASE_TYPE_STRING
- ? 1
- : InlineSize(field.value.type.VectorType()));
- // Generate a ByteBuffer accessor for strings & vectors of scalars.
- // e.g.
- // val inventoryByteBuffer: ByteBuffer
- // get = __vector_as_bytebuffer(14, 1)
-
- GenerateGetterOneLine(writer, field_name + "AsByteBuffer",
- "ByteBuffer", [&](){
- writer.SetValue("end", end_idx);
- writer += "__vector_as_bytebuffer({{offset}}, {{end}})";
- });
-
- // Generate a ByteBuffer accessor for strings & vectors of scalars.
- // e.g.
- // fun inventoryInByteBuffer(_bb: Bytebuffer):
- // ByteBuffer = __vector_as_bytebuffer(_bb, 14, 1)
- GenerateFunOneLine(writer, field_name + "InByteBuffer",
- "_bb: ByteBuffer", "ByteBuffer", [&](){
- writer.SetValue("end", end_idx);
- writer += "__vector_in_bytebuffer(_bb, {{offset}}, {{end}})";
- });
- }
+ // generate object accessors if is nested_flatbuffer
+ // fun testnestedflatbufferAsMonster() : Monster?
+ //{ return testnestedflatbufferAsMonster(new Monster()); }
- // generate object accessors if is nested_flatbuffer
- //fun testnestedflatbufferAsMonster() : Monster?
- //{ return testnestedflatbufferAsMonster(new Monster()); }
-
- if (field.nested_flatbuffer) {
- auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
- auto nested_method_name =
- field_name + "As" +
- field.nested_flatbuffer->name;
-
- GenerateGetterOneLine(writer,
- nested_method_name,
- nested_type_name + "?", [&](){
- writer += nested_method_name + "(" + nested_type_name + "())";
- });
-
- GenerateFun(writer,
- nested_method_name,
- "obj: " + nested_type_name,
- nested_type_name + "?", [&](){
- OffsetWrapper(writer, offset_val,
- [&]() { writer += "obj.__assign(__indirect(__vector(o)), bb)"; },
- [&]() { writer += "null";});
- });
- }
+ if (field.nested_flatbuffer) {
+ auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
+ auto nested_method_name =
+ field_name + "As" + field.nested_flatbuffer->name;
- // Generate mutators for scalar fields or vectors of scalars.
- if (parser_.opts.mutable_buffer) {
- auto value_type = field.value.type;
- auto underlying_type = value_base_type == BASE_TYPE_VECTOR
- ? value_type.VectorType()
- : value_type;
- auto name = "mutate" + MakeCamel(Esc(field.name), true);
- auto size = NumToString(InlineSize(underlying_type));
- auto params = Esc(field.name) + ": " + 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, ");
-
- // Boolean parameters have to be explicitly converted to byte
- // representation.
- auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
- ? "(if(" + Esc(field.name) + ") 1 else 0).toByte()"
- : Esc(field.name);
-
- auto setter_index = value_base_type == BASE_TYPE_VECTOR
- ? "__vector(o) + j * " + size
- : (struct_def.fixed
- ? "bb_pos + " + offset_val
- : "o + bb_pos");
- if (IsScalar(value_base_type) || (value_base_type == BASE_TYPE_VECTOR &&
- IsScalar(value_type.VectorType().base_type))) {
-
- auto statements = [&] () {
- writer.SetValue("bbsetter", ByteBufferSetter(underlying_type));
- writer.SetValue("index", setter_index);
- writer.SetValue("params", setter_parameter);
- writer.SetValue("cast", CastToSigned(field));
- if (struct_def.fixed) {
- writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})";
- } else {
- OffsetWrapper(writer, offset_val, [&](){
- writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})";
- writer += "true";
- }, [&](){ writer += "false";});
- }
- };
-
- if (struct_def.fixed) {
- GenerateFunOneLine(writer, name, params, "ByteBuffer",
- statements);
- } else {
- GenerateFun(writer, name, params, "Boolean",
- statements);
- }
- }
- }
- }
- if (struct_def.has_key && !struct_def.fixed) {
- // Key Comparison method
- GenerateOverrideFun(
- writer,
- "keysCompare",
- "o1: Int, o2: Int, _bb: ByteBuffer", "Int", [&]() {
- if (key_field->value.type.base_type == BASE_TYPE_STRING) {
- writer.SetValue("offset", NumToString(key_field->value.offset));
- writer += " return compareStrings(__offset({{offset}}, o1, "
- "_bb), __offset({{offset}}, o2, _bb), _bb)";
-
- } else {
- auto getter1 = GenLookupByKey(key_field, "_bb", "o1");
- auto getter2 = GenLookupByKey(key_field, "_bb", "o2");
- writer += "val val_1 = " + getter1;
- writer += "val val_2 = " + getter2;
- writer += "return (val_1 - val_2).sign";
- }
+ GenerateGetterOneLine(
+ writer, nested_method_name, nested_type_name + "?", [&]() {
+ writer += nested_method_name + "(" + nested_type_name + "())";
});
- }
- }
- static std::string CastToUsigned(const FieldDef &field) {
- return CastToUsigned(field.value.type);
- }
-
- static std::string CastToUsigned(const Type type) {
- switch (type.base_type) {
- case BASE_TYPE_UINT:
- return ".toUInt()";
- case BASE_TYPE_UCHAR:
- case BASE_TYPE_UTYPE:
- return ".toUByte()";
- case BASE_TYPE_USHORT:
- return ".toUShort()";
- case BASE_TYPE_ULONG:
- return ".toULong()";
- case BASE_TYPE_VECTOR:
- return CastToUsigned(type.VectorType());
- default:
- return "";
- }
- }
+ GenerateFun(writer, nested_method_name, "obj: " + nested_type_name,
+ nested_type_name + "?", [&]() {
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() {
+ writer +=
+ "obj.__assign(__indirect(__vector(o)), bb)";
+ },
+ [&]() { writer += "null"; });
+ });
+ }
- static std::string CastToSigned(const FieldDef &field) {
- return CastToSigned(field.value.type);
- }
+ // Generate mutators for scalar fields or vectors of scalars.
+ if (parser_.opts.mutable_buffer) {
+ auto value_type = field.value.type;
+ auto underlying_type = value_base_type == BASE_TYPE_VECTOR
+ ? value_type.VectorType()
+ : value_type;
+ auto name = "mutate" + MakeCamel(Esc(field.name), true);
+ auto size = NumToString(InlineSize(underlying_type));
+ auto params = Esc(field.name) + ": " + 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, ");
+
+ // Boolean parameters have to be explicitly converted to byte
+ // representation.
+ auto setter_parameter =
+ underlying_type.base_type == BASE_TYPE_BOOL
+ ? "(if(" + Esc(field.name) + ") 1 else 0).toByte()"
+ : Esc(field.name);
+
+ auto setter_index =
+ value_base_type == BASE_TYPE_VECTOR
+ ? "__vector(o) + j * " + size
+ : (struct_def.fixed ? "bb_pos + " + offset_val : "o + bb_pos");
+ if (IsScalar(value_base_type) ||
+ (value_base_type == BASE_TYPE_VECTOR &&
+ IsScalar(value_type.VectorType().base_type))) {
+ auto statements = [&]() {
+ writer.SetValue("bbsetter", ByteBufferSetter(underlying_type));
+ writer.SetValue("index", setter_index);
+ writer.SetValue("params", setter_parameter);
+ writer.SetValue("cast", CastToSigned(field));
+ if (struct_def.fixed) {
+ writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})";
+ } else {
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() {
+ writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})";
+ writer += "true";
+ },
+ [&]() { writer += "false"; });
+ }
+ };
- static std::string CastToSigned(const Type type) {
- switch (type.base_type) {
- case BASE_TYPE_UINT:
- return ".toInt()";
- case BASE_TYPE_UCHAR:
- case BASE_TYPE_UTYPE:
- return ".toByte()";
- case BASE_TYPE_USHORT:
- return ".toShort()";
- case BASE_TYPE_ULONG:
- return ".toLong()";
- case BASE_TYPE_VECTOR:
- return CastToSigned(type.VectorType());
- default:
- return "";
+ if (struct_def.fixed) {
+ GenerateFunOneLine(writer, name, params, "ByteBuffer", statements);
+ } else {
+ GenerateFun(writer, name, params, "Boolean", statements);
+ }
}
+ }
}
+ if (struct_def.has_key && !struct_def.fixed) {
+ // Key Comparison method
+ GenerateOverrideFun(
+ writer, "keysCompare", "o1: Int, o2: Int, _bb: ByteBuffer", "Int",
+ [&]() {
+ if (key_field->value.type.base_type == BASE_TYPE_STRING) {
+ writer.SetValue("offset", NumToString(key_field->value.offset));
+ writer +=
+ " return compareStrings(__offset({{offset}}, o1, "
+ "_bb), __offset({{offset}}, o2, _bb), _bb)";
- static std::string LiteralSuffix(const BaseType type) {
- switch (type) {
- case BASE_TYPE_UINT:
- case BASE_TYPE_UCHAR:
- case BASE_TYPE_UTYPE:
- case BASE_TYPE_USHORT:
- return "u";
- case BASE_TYPE_ULONG:
- return "UL";
- case BASE_TYPE_LONG:
- return "L";
- default:
- return "";
- }
+ } else {
+ auto getter1 = GenLookupByKey(key_field, "_bb", "o1");
+ auto getter2 = GenLookupByKey(key_field, "_bb", "o2");
+ writer += "val val_1 = " + getter1;
+ writer += "val val_2 = " + getter2;
+ writer += "return (val_1 - val_2).sign";
+ }
+ });
}
+ }
+
+ static std::string CastToUsigned(const FieldDef &field) {
+ return CastToUsigned(field.value.type);
+ }
- void GenerateCompanionObject(CodeWriter &code,
- const std::function<void()> &callback) const {
- code += "companion object {";
- code.IncrementIdentLevel();
- callback();
- code.DecrementIdentLevel();
- code += "}";
+ static std::string CastToUsigned(const Type type) {
+ switch (type.base_type) {
+ case BASE_TYPE_UINT: return ".toUInt()";
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_UTYPE: return ".toUByte()";
+ case BASE_TYPE_USHORT: return ".toUShort()";
+ case BASE_TYPE_ULONG: return ".toULong()";
+ case BASE_TYPE_VECTOR: return CastToUsigned(type.VectorType());
+ default: return "";
}
+ }
- // Generate a documentation comment, if available.
- void GenerateComment(const std::vector<std::string> &dc, CodeWriter &writer,
- const CommentConfig *config) const {
- if (dc.begin() == dc.end()) {
- // Don't output empty comment blocks with 0 lines of comment content.
- return;
- }
+ static std::string CastToSigned(const FieldDef &field) {
+ return CastToSigned(field.value.type);
+ }
- if (config != nullptr && config->first_line != nullptr) {
- writer += std::string(config->first_line);
- }
- std::string line_prefix =
- ((config != nullptr && config->content_line_prefix != nullptr)
- ? config->content_line_prefix
- : "///");
- for (auto it = dc.begin(); it != dc.end(); ++it) {
- writer += line_prefix + *it;
- }
- if (config != nullptr && config->last_line != nullptr) {
- writer += std::string(config->last_line);
- }
+ static std::string CastToSigned(const Type type) {
+ switch (type.base_type) {
+ case BASE_TYPE_UINT: return ".toInt()";
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_UTYPE: return ".toByte()";
+ case BASE_TYPE_USHORT: return ".toShort()";
+ case BASE_TYPE_ULONG: return ".toLong()";
+ case BASE_TYPE_VECTOR: return CastToSigned(type.VectorType());
+ default: return "";
}
+ }
- static void GenerateGetRootAsAccessors(const std::string &struct_name,
- CodeWriter &writer) {
- // 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);
- writer.SetValue("gr_method", "getRootAs" + struct_name);
-
- // create convenience method that doesn't require an existing object
- writer += "fun {{gr_method}}(_bb: ByteBuffer): {{gr_name}} = \\";
- writer += "{{gr_method}}(_bb, {{gr_name}}())";
-
- // create method that allows object reuse
- // ex: fun Monster getRootAsMonster(_bb: ByteBuffer, obj: Monster) {...}
- writer += "fun {{gr_method}}"
- "(_bb: ByteBuffer, obj: {{gr_name}}): {{gr_name}} {";
- writer.IncrementIdentLevel();
- writer += "_bb.order(ByteOrder.LITTLE_ENDIAN)";
- writer += "return (obj.__assign(_bb.getInt(_bb.position())"
- " + _bb.position(), _bb))";
- writer.DecrementIdentLevel();
- writer += "}";
+ static std::string LiteralSuffix(const BaseType type) {
+ switch (type) {
+ case BASE_TYPE_UINT:
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_UTYPE:
+ case BASE_TYPE_USHORT: return "u";
+ case BASE_TYPE_ULONG: return "UL";
+ case BASE_TYPE_LONG: return "L";
+ default: return "";
}
+ }
- static void GenerateStaticConstructor(const StructDef &struct_def,
- CodeWriter &code) {
- // create a struct constructor function
- auto params = StructConstructorParams(struct_def);
- GenerateFun(code, "create" + Esc(struct_def.name), params, "Int", [&](){
- GenStructBody(struct_def, code, "");
- code += "return builder.offset()";
- });
- }
+ void GenerateCompanionObject(CodeWriter &code,
+ const std::function<void()> &callback) const {
+ code += "companion object {";
+ code.IncrementIdentLevel();
+ callback();
+ code.DecrementIdentLevel();
+ code += "}";
+ }
- static std::string StructConstructorParams(const StructDef &struct_def,
- const std::string &prefix = "") {
- //builder: FlatBufferBuilder
- std::stringstream out;
- auto field_vec = struct_def.fields.vec;
- if (prefix.empty()) {
- out << "builder: FlatBufferBuilder";
- }
- for (auto it = field_vec.begin(); it != field_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.
- out << StructConstructorParams(*field.value.type.struct_def,
- prefix + (Esc(field.name) + "_"));
- } else {
- out << ", " << prefix << MakeCamel(Esc(field.name), false)
- << ": "
- << GenTypeBasic(field.value.type.base_type);
- }
- }
- return out.str();
+ // Generate a documentation comment, if available.
+ void GenerateComment(const std::vector<std::string> &dc, CodeWriter &writer,
+ const CommentConfig *config) const {
+ if (dc.begin() == dc.end()) {
+ // Don't output empty comment blocks with 0 lines of comment content.
+ return;
}
- static void GeneratePropertyOneLine(CodeWriter &writer,
- const std::string &name,
- const std::string &type,
- const std::function<void()> &body) {
- // Generates Kotlin getter for properties
- // e.g.:
- // val prop: Mytype = x
- writer.SetValue("_name", name);
- writer.SetValue("_type", type);
- writer += "val {{_name}} : {{_type}} = \\";
- body();
+ if (config != nullptr && config->first_line != nullptr) {
+ writer += std::string(config->first_line);
}
- static void GenerateGetterOneLine(CodeWriter &writer,
- const std::string &name,
- const std::string &type,
- const std::function<void()> &body) {
- // Generates Kotlin getter for properties
- // e.g.:
- // val prop: Mytype get() = x
- writer.SetValue("_name", name);
- writer.SetValue("_type", type);
- writer += "val {{_name}} : {{_type}} get() = \\";
- body();
+ std::string line_prefix =
+ ((config != nullptr && config->content_line_prefix != nullptr)
+ ? config->content_line_prefix
+ : "///");
+ for (auto it = dc.begin(); it != dc.end(); ++it) {
+ writer += line_prefix + *it;
}
-
- static void GenerateGetter(CodeWriter &writer,
- const std::string &name,
- const std::string &type,
- const std::function<void()> &body) {
- // Generates Kotlin getter for properties
- // e.g.:
- // val prop: Mytype
- // get() = {
- // return x
- // }
- writer.SetValue("name", name);
- writer.SetValue("type", type);
- writer += "val {{name}} : {{type}}";
- writer.IncrementIdentLevel();
- writer += "get() {";
- writer.IncrementIdentLevel();
- body();
- writer.DecrementIdentLevel();
- writer += "}";
- writer.DecrementIdentLevel();
+ if (config != nullptr && config->last_line != nullptr) {
+ writer += std::string(config->last_line);
}
+ }
- static void GenerateFun(CodeWriter &writer,
- const std::string &name,
- const std::string ¶ms,
- const std::string &returnType,
- const std::function<void()> &body) {
- // Generates Kotlin function
- // e.g.:
- // fun path(j: Int): Vec3 {
- // return path(Vec3(), j)
- // }
- auto noreturn = returnType.empty();
- writer.SetValue("name", name);
- writer.SetValue("params", params);
- writer.SetValue("return_type", noreturn ? "" : ": " + returnType);
- writer += "fun {{name}}({{params}}) {{return_type}} {";
- writer.IncrementIdentLevel();
- body();
- writer.DecrementIdentLevel();
- writer += "}";
- }
+ static void GenerateGetRootAsAccessors(const std::string &struct_name,
+ CodeWriter &writer) {
+ // 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);
+ writer.SetValue("gr_method", "getRootAs" + struct_name);
+
+ // create convenience method that doesn't require an existing object
+ writer += "fun {{gr_method}}(_bb: ByteBuffer): {{gr_name}} = \\";
+ writer += "{{gr_method}}(_bb, {{gr_name}}())";
+
+ // create method that allows object reuse
+ // ex: fun Monster getRootAsMonster(_bb: ByteBuffer, obj: Monster) {...}
+ writer +=
+ "fun {{gr_method}}"
+ "(_bb: ByteBuffer, obj: {{gr_name}}): {{gr_name}} {";
+ writer.IncrementIdentLevel();
+ writer += "_bb.order(ByteOrder.LITTLE_ENDIAN)";
+ writer +=
+ "return (obj.__assign(_bb.getInt(_bb.position())"
+ " + _bb.position(), _bb))";
+ writer.DecrementIdentLevel();
+ writer += "}";
+ }
- static void GenerateFunOneLine(CodeWriter &writer,
- const std::string &name,
- const std::string ¶ms,
- const std::string &returnType,
- const std::function<void()> &body) {
- // Generates Kotlin function
- // e.g.:
- // fun path(j: Int): Vec3 = return path(Vec3(), j)
- writer.SetValue("name", name);
- writer.SetValue("params", params);
- writer.SetValue("return_type_p", returnType.empty() ? "" :
- " : " + returnType);
- writer += "fun {{name}}({{params}}){{return_type_p}} = \\";
- body();
- }
+ static void GenerateStaticConstructor(const StructDef &struct_def,
+ CodeWriter &code) {
+ // create a struct constructor function
+ auto params = StructConstructorParams(struct_def);
+ GenerateFun(code, "create" + Esc(struct_def.name), params, "Int", [&]() {
+ GenStructBody(struct_def, code, "");
+ code += "return builder.offset()";
+ });
+ }
- static void GenerateOverrideFun(CodeWriter &writer,
- const std::string &name,
- const std::string ¶ms,
- const std::string &returnType,
- const std::function<void()> &body) {
- // Generates Kotlin function
- // e.g.:
- // override fun path(j: Int): Vec3 = return path(Vec3(), j)
- writer += "override \\";
- GenerateFun(writer, name, params, returnType, body);
+ static std::string StructConstructorParams(const StructDef &struct_def,
+ const std::string &prefix = "") {
+ // builder: FlatBufferBuilder
+ std::stringstream out;
+ auto field_vec = struct_def.fields.vec;
+ if (prefix.empty()) { out << "builder: FlatBufferBuilder"; }
+ for (auto it = field_vec.begin(); it != field_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.
+ out << StructConstructorParams(*field.value.type.struct_def,
+ prefix + (Esc(field.name) + "_"));
+ } else {
+ out << ", " << prefix << MakeCamel(Esc(field.name), false) << ": "
+ << GenTypeBasic(field.value.type.base_type);
+ }
}
+ return out.str();
+ }
- static void GenerateOverrideFunOneLine(CodeWriter &writer,
- const std::string &name,
- const std::string ¶ms,
- const std::string &returnType,
- const std::string &statement) {
- // Generates Kotlin function
- // e.g.:
- // override fun path(j: Int): Vec3 = return path(Vec3(), j)
- writer.SetValue("name", name);
- writer.SetValue("params", params);
- writer.SetValue("return_type", returnType.empty() ? "" :
- " : " + returnType);
- writer += "override fun {{name}}({{params}}){{return_type}} = \\";
- writer += statement;
- }
+ static void GeneratePropertyOneLine(CodeWriter &writer,
+ const std::string &name,
+ const std::string &type,
+ const std::function<void()> &body) {
+ // Generates Kotlin getter for properties
+ // e.g.:
+ // val prop: Mytype = x
+ writer.SetValue("_name", name);
+ writer.SetValue("_type", type);
+ writer += "val {{_name}} : {{_type}} = \\";
+ body();
+ }
+ static void GenerateGetterOneLine(CodeWriter &writer, const std::string &name,
+ const std::string &type,
+ const std::function<void()> &body) {
+ // Generates Kotlin getter for properties
+ // e.g.:
+ // val prop: Mytype get() = x
+ writer.SetValue("_name", name);
+ writer.SetValue("_type", type);
+ writer += "val {{_name}} : {{_type}} get() = \\";
+ body();
+ }
- static std::string OffsetWrapperOneLine(const std::string &offset,
- const std::string &found,
- const std::string ¬_found) {
- return "val o = __offset(" + offset + "); return if (o != 0) " + found +
- " else " + not_found;
- }
+ static void GenerateGetter(CodeWriter &writer, const std::string &name,
+ const std::string &type,
+ const std::function<void()> &body) {
+ // Generates Kotlin getter for properties
+ // e.g.:
+ // val prop: Mytype
+ // get() = {
+ // return x
+ // }
+ writer.SetValue("name", name);
+ writer.SetValue("type", type);
+ writer += "val {{name}} : {{type}}";
+ writer.IncrementIdentLevel();
+ writer += "get() {";
+ writer.IncrementIdentLevel();
+ body();
+ writer.DecrementIdentLevel();
+ writer += "}";
+ writer.DecrementIdentLevel();
+ }
- static void OffsetWrapper(CodeWriter &code,
- const std::string &offset,
- const std::function<void()> &found,
- const std::function<void()> ¬_found) {
- code += "val o = __offset(" + offset + ")";
- code +="return if (o != 0) {";
- code.IncrementIdentLevel();
- found();
- code.DecrementIdentLevel();
- code += "} else {";
- code.IncrementIdentLevel();
- not_found();
- code.DecrementIdentLevel();
- code += "}";
- }
+ static void GenerateFun(CodeWriter &writer, const std::string &name,
+ const std::string ¶ms,
+ const std::string &returnType,
+ const std::function<void()> &body) {
+ // Generates Kotlin function
+ // e.g.:
+ // fun path(j: Int): Vec3 {
+ // return path(Vec3(), j)
+ // }
+ auto noreturn = returnType.empty();
+ writer.SetValue("name", name);
+ writer.SetValue("params", params);
+ writer.SetValue("return_type", noreturn ? "" : ": " + returnType);
+ writer += "fun {{name}}({{params}}) {{return_type}} {";
+ writer.IncrementIdentLevel();
+ body();
+ writer.DecrementIdentLevel();
+ writer += "}";
+ }
- static std::string Indirect(const std::string &index, bool fixed) {
- // We apply __indirect() and struct is not fixed.
- if (!fixed)
- return "__indirect(" + index + ")";
- return index;
- }
+ static void GenerateFunOneLine(CodeWriter &writer, const std::string &name,
+ const std::string ¶ms,
+ const std::string &returnType,
+ const std::function<void()> &body) {
+ // Generates Kotlin function
+ // e.g.:
+ // fun path(j: Int): Vec3 = return path(Vec3(), j)
+ writer.SetValue("name", name);
+ writer.SetValue("params", params);
+ writer.SetValue("return_type_p",
+ returnType.empty() ? "" : " : " + returnType);
+ writer += "fun {{name}}({{params}}){{return_type_p}} = \\";
+ body();
+ }
- static std::string NotFoundReturn(BaseType el) {
- switch (el) {
- case BASE_TYPE_FLOAT:
- return "0.0f";
- case BASE_TYPE_DOUBLE:
- return "0.0";
- case BASE_TYPE_BOOL:
- return "false";
- case BASE_TYPE_LONG:
- case BASE_TYPE_INT:
- case BASE_TYPE_CHAR:
- case BASE_TYPE_SHORT:
- return "0";
- case BASE_TYPE_UINT:
- case BASE_TYPE_UCHAR:
- case BASE_TYPE_USHORT:
- case BASE_TYPE_UTYPE:
- return "0u";
- case BASE_TYPE_ULONG:
- return "0uL";
- default:
- return "null";
- }
+ static void GenerateOverrideFun(CodeWriter &writer, const std::string &name,
+ const std::string ¶ms,
+ const std::string &returnType,
+ const std::function<void()> &body) {
+ // Generates Kotlin function
+ // e.g.:
+ // override fun path(j: Int): Vec3 = return path(Vec3(), j)
+ writer += "override \\";
+ GenerateFun(writer, name, params, returnType, body);
+ }
+
+ static void GenerateOverrideFunOneLine(CodeWriter &writer,
+ const std::string &name,
+ const std::string ¶ms,
+ const std::string &returnType,
+ const std::string &statement) {
+ // Generates Kotlin function
+ // e.g.:
+ // override fun path(j: Int): Vec3 = return path(Vec3(), j)
+ writer.SetValue("name", name);
+ writer.SetValue("params", params);
+ writer.SetValue("return_type",
+ returnType.empty() ? "" : " : " + returnType);
+ writer += "override fun {{name}}({{params}}){{return_type}} = \\";
+ writer += statement;
+ }
+
+ static std::string OffsetWrapperOneLine(const std::string &offset,
+ const std::string &found,
+ const std::string ¬_found) {
+ return "val o = __offset(" + offset + "); return if (o != 0) " + found +
+ " else " + not_found;
+ }
+
+ static void OffsetWrapper(CodeWriter &code, const std::string &offset,
+ const std::function<void()> &found,
+ const std::function<void()> ¬_found) {
+ code += "val o = __offset(" + offset + ")";
+ code += "return if (o != 0) {";
+ code.IncrementIdentLevel();
+ found();
+ code.DecrementIdentLevel();
+ code += "} else {";
+ code.IncrementIdentLevel();
+ not_found();
+ code.DecrementIdentLevel();
+ code += "}";
+ }
+
+ static std::string Indirect(const std::string &index, bool fixed) {
+ // We apply __indirect() and struct is not fixed.
+ if (!fixed) return "__indirect(" + index + ")";
+ return index;
+ }
+
+ static std::string NotFoundReturn(BaseType el) {
+ switch (el) {
+ case BASE_TYPE_FLOAT: return "0.0f";
+ case BASE_TYPE_DOUBLE: return "0.0";
+ case BASE_TYPE_BOOL: return "false";
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_INT:
+ case BASE_TYPE_CHAR:
+ case BASE_TYPE_SHORT: return "0";
+ case BASE_TYPE_UINT:
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_USHORT:
+ case BASE_TYPE_UTYPE: return "0u";
+ case BASE_TYPE_ULONG: return "0uL";
+ default: return "null";
}
+ }
- // This tracks the current namespace used to determine if a type need to be
- // prefixed by its namespace
- const Namespace *cur_name_space_;
+ // This tracks the current namespace used to determine if a type need to be
+ // prefixed by its namespace
+ const Namespace *cur_name_space_;
};
} // namespace kotlin
bool GenerateKotlin(const Parser &parser, const std::string &path,
const std::string &file_name) {
- kotlin::KotlinGenerator generator(parser, path, file_name);
- return generator.generate();
+ kotlin::KotlinGenerator generator(parser, path, file_name);
+ return generator.generate();
}
} // namespace flatbuffers