Commit 00694d27 authored by Romain Gilles's avatar Romain Gilles

Merge branch 'master' of github.com:google/flatbuffers

parents 7a955a09 b22db6e8
...@@ -288,7 +288,7 @@ public: ...@@ -288,7 +288,7 @@ public:
} }
VectorIterator operator++(int) { VectorIterator operator++(int) {
VectorIterator temp(data_); VectorIterator temp(data_,0);
data_ += IndirectHelper<T>::element_stride; data_ += IndirectHelper<T>::element_stride;
return temp; return temp;
} }
...@@ -876,7 +876,7 @@ FLATBUFFERS_FINAL_CLASS ...@@ -876,7 +876,7 @@ FLATBUFFERS_FINAL_CLASS
/// @param[in] str A const pointer to a `String` struct to add to the buffer. /// @param[in] str A const pointer to a `String` struct to add to the buffer.
/// @return Returns the offset in the buffer where the string starts /// @return Returns the offset in the buffer where the string starts
Offset<String> CreateString(const String *str) { Offset<String> CreateString(const String *str) {
return CreateString(str->c_str(), str->Length()); return str ? CreateString(str->c_str(), str->Length()) : 0;
} }
/// @brief Store a string in the buffer, which can contain any binary data. /// @brief Store a string in the buffer, which can contain any binary data.
...@@ -1216,6 +1216,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS { ...@@ -1216,6 +1216,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
size_t _max_tables = 1000000) size_t _max_tables = 1000000)
: buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth), : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
num_tables_(0), max_tables_(_max_tables) num_tables_(0), max_tables_(_max_tables)
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
, upper_bound_(buf)
#endif
{} {}
// Central location where any verification failures register. // Central location where any verification failures register.
...@@ -1223,11 +1226,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS { ...@@ -1223,11 +1226,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
assert(ok); assert(ok);
#endif #endif
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
if (!ok)
upper_bound_ = buf_;
#endif
return ok; return ok;
} }
// Verify any range within the buffer. // Verify any range within the buffer.
bool Verify(const void *elem, size_t elem_len) const { bool Verify(const void *elem, size_t elem_len) const {
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
auto upper_bound = reinterpret_cast<const uint8_t *>(elem) + elem_len;
if (upper_bound_ < upper_bound)
upper_bound_ = upper_bound;
#endif
return Check(elem_len <= (size_t) (end_ - buf_) && return Check(elem_len <= (size_t) (end_ - buf_) &&
elem >= buf_ && elem >= buf_ &&
elem <= end_ - elem_len); elem <= end_ - elem_len);
...@@ -1302,11 +1314,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS { ...@@ -1302,11 +1314,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
} }
// Verify this whole buffer, starting with root type T. // Verify this whole buffer, starting with root type T.
template<typename T> bool VerifyBuffer() { template<typename T> bool VerifyBuffer(const char *identifier) {
if (identifier && (size_t(end_ - buf_) < 2 * sizeof(flatbuffers::uoffset_t) ||
!BufferHasIdentifier(buf_, identifier))) {
return false;
}
// Call T::Verify, which must be in the generated code for this type. // Call T::Verify, which must be in the generated code for this type.
return Verify<uoffset_t>(buf_) && return Verify<uoffset_t>(buf_) &&
reinterpret_cast<const T *>(buf_ + ReadScalar<uoffset_t>(buf_))-> reinterpret_cast<const T *>(buf_ + ReadScalar<uoffset_t>(buf_))->
Verify(*this); Verify(*this)
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
&& GetComputedSize()
#endif
;
} }
// Called at the start of a table to increase counters measuring data // Called at the start of a table to increase counters measuring data
...@@ -1325,6 +1346,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS { ...@@ -1325,6 +1346,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return true; return true;
} }
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
// Returns the message size in bytes
size_t GetComputedSize() const {
uintptr_t size = upper_bound_ - buf_;
// Align the size to uoffset_t
size = (size - 1 + sizeof(uoffset_t)) & -uintptr_t(sizeof(uoffset_t));
return (buf_ + size > end_) ? 0 : size;
}
#endif
private: private:
const uint8_t *buf_; const uint8_t *buf_;
const uint8_t *end_; const uint8_t *end_;
...@@ -1332,6 +1363,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS { ...@@ -1332,6 +1363,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
size_t max_depth_; size_t max_depth_;
size_t num_tables_; size_t num_tables_;
size_t max_tables_; size_t max_tables_;
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
mutable const uint8_t *upper_bound_;
#endif
}; };
// Convenient way to bundle a buffer and its length, to pass it around // Convenient way to bundle a buffer and its length, to pass it around
......
...@@ -337,7 +337,8 @@ struct IDLOptions { ...@@ -337,7 +337,8 @@ struct IDLOptions {
bool generate_all; bool generate_all;
bool skip_unexpected_fields_in_json; bool skip_unexpected_fields_in_json;
bool generate_name_strings; bool generate_name_strings;
bool escape_proto_identifiers;
// Possible options for the more general generator below. // Possible options for the more general generator below.
enum Language { kJava, kCSharp, kGo, kMAX }; enum Language { kJava, kCSharp, kGo, kMAX };
...@@ -356,6 +357,7 @@ struct IDLOptions { ...@@ -356,6 +357,7 @@ struct IDLOptions {
generate_all(false), generate_all(false),
skip_unexpected_fields_in_json(false), skip_unexpected_fields_in_json(false),
generate_name_strings(false), generate_name_strings(false),
escape_proto_identifiers(false),
lang(IDLOptions::kJava) {} lang(IDLOptions::kJava) {}
}; };
......
...@@ -478,12 +478,12 @@ inline flatbuffers::Offset<Schema> CreateSchema(flatbuffers::FlatBufferBuilder & ...@@ -478,12 +478,12 @@ inline flatbuffers::Offset<Schema> CreateSchema(flatbuffers::FlatBufferBuilder &
inline const reflection::Schema *GetSchema(const void *buf) { return flatbuffers::GetRoot<reflection::Schema>(buf); } inline const reflection::Schema *GetSchema(const void *buf) { return flatbuffers::GetRoot<reflection::Schema>(buf); }
inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<reflection::Schema>(); }
inline const char *SchemaIdentifier() { return "BFBS"; } inline const char *SchemaIdentifier() { return "BFBS"; }
inline bool SchemaBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, SchemaIdentifier()); } inline bool SchemaBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, SchemaIdentifier()); }
inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier()); }
inline const char *SchemaExtension() { return "bfbs"; } inline const char *SchemaExtension() { return "bfbs"; }
inline void FinishSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<reflection::Schema> root) { fbb.Finish(root, SchemaIdentifier()); } inline void FinishSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<reflection::Schema> root) { fbb.Finish(root, SchemaIdentifier()); }
......
...@@ -135,15 +135,15 @@ struct MonsterBuilder { ...@@ -135,15 +135,15 @@ struct MonsterBuilder {
}; };
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
const Vec3 *pos = 0, const Vec3 *pos = 0,
int16_t mana = 150, int16_t mana = 150,
int16_t hp = 100, int16_t hp = 100,
flatbuffers::Offset<flatbuffers::String> name = 0, flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory = 0, flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory = 0,
Color color = Color_Blue, Color color = Color_Blue,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Weapon>>> weapons = 0, flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Weapon>>> weapons = 0,
Equipment equipped_type = Equipment_NONE, Equipment equipped_type = Equipment_NONE,
flatbuffers::Offset<void> equipped = 0) { flatbuffers::Offset<void> equipped = 0) {
MonsterBuilder builder_(_fbb); MonsterBuilder builder_(_fbb);
builder_.add_equipped(equipped); builder_.add_equipped(equipped);
builder_.add_weapons(weapons); builder_.add_weapons(weapons);
...@@ -157,6 +157,19 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder ...@@ -157,6 +157,19 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
return builder_.Finish(); return builder_.Finish();
} }
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
const Vec3 *pos = 0,
int16_t mana = 150,
int16_t hp = 100,
const char *name = nullptr,
const std::vector<uint8_t> *inventory = nullptr,
Color color = Color_Blue,
const std::vector<flatbuffers::Offset<Weapon>> *weapons = nullptr,
Equipment equipped_type = Equipment_NONE,
flatbuffers::Offset<void> equipped = 0) {
return CreateMonster(_fbb, pos, mana, hp, name ? 0 : _fbb.CreateString(name), inventory ? 0 : _fbb.CreateVector<uint8_t>(*inventory), color, weapons ? 0 : _fbb.CreateVector<flatbuffers::Offset<Weapon>>(*weapons), equipped_type, equipped);
}
struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum { enum {
VT_NAME = 4, VT_NAME = 4,
...@@ -189,14 +202,20 @@ struct WeaponBuilder { ...@@ -189,14 +202,20 @@ struct WeaponBuilder {
}; };
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0, flatbuffers::Offset<flatbuffers::String> name = 0,
int16_t damage = 0) { int16_t damage = 0) {
WeaponBuilder builder_(_fbb); WeaponBuilder builder_(_fbb);
builder_.add_name(name); builder_.add_name(name);
builder_.add_damage(damage); builder_.add_damage(damage);
return builder_.Finish(); return builder_.Finish();
} }
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
int16_t damage = 0) {
return CreateWeapon(_fbb, name ? 0 : _fbb.CreateString(name), damage);
}
inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_obj, Equipment type) { inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_obj, Equipment type) {
switch (type) { switch (type) {
case Equipment_NONE: return true; case Equipment_NONE: return true;
...@@ -209,7 +228,7 @@ inline const MyGame::Sample::Monster *GetMonster(const void *buf) { return flatb ...@@ -209,7 +228,7 @@ inline const MyGame::Sample::Monster *GetMonster(const void *buf) { return flatb
inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot<Monster>(buf); } inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot<Monster>(buf); }
inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Sample::Monster>(); } inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Sample::Monster>(nullptr); }
inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Sample::Monster> root) { fbb.Finish(root); } inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Sample::Monster> root) { fbb.Finish(root); }
......
...@@ -120,8 +120,9 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) { ...@@ -120,8 +120,9 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) {
" --no-includes Don\'t generate include statements for included\n" " --no-includes Don\'t generate include statements for included\n"
" schemas the generated file depends on (C++).\n" " schemas the generated file depends on (C++).\n"
" --gen-mutable Generate accessors that can mutate buffers in-place.\n" " --gen-mutable Generate accessors that can mutate buffers in-place.\n"
" --gen-onefile Generate single output file for C#\n" " --gen-onefile Generate single output file for C#.\n"
" --gen-name-strings Generate type name functions for C++.\n" " --gen-name-strings Generate type name functions for C++.\n"
" --escape-proto-ids Disable appending '_' in namespaces names.\n"
" --raw-binary Allow binaries without file_indentifier to be read.\n" " --raw-binary Allow binaries without file_indentifier to be read.\n"
" This may crash flatc given a mismatched schema.\n" " This may crash flatc given a mismatched schema.\n"
" --proto Input is a .proto, translate to .fbs.\n" " --proto Input is a .proto, translate to .fbs.\n"
...@@ -194,6 +195,8 @@ int main(int argc, const char *argv[]) { ...@@ -194,6 +195,8 @@ int main(int argc, const char *argv[]) {
binary_files_from = filenames.size(); binary_files_from = filenames.size();
} else if(arg == "--proto") { } else if(arg == "--proto") {
opts.proto_mode = true; opts.proto_mode = true;
} else if(arg == "--escape-proto-ids") {
opts.escape_proto_identifiers = true;
} else if(arg == "--schema") { } else if(arg == "--schema") {
schema_binary = true; schema_binary = true;
} else if(arg == "-M") { } else if(arg == "-M") {
......
...@@ -39,7 +39,8 @@ class CppGenerator : public BaseGenerator { ...@@ -39,7 +39,8 @@ class CppGenerator : public BaseGenerator {
public: public:
CppGenerator(const Parser &parser, const std::string &path, CppGenerator(const Parser &parser, const std::string &path,
const std::string &file_name) const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "::"){}; : BaseGenerator(parser, path, file_name, "", "::"),
cur_name_space_(nullptr){};
// Iterate through all definitions we haven't generate code for (enums, // Iterate through all definitions we haven't generate code for (enums,
// structs, // structs,
// and tables) and output them to a single file. // and tables) and output them to a single file.
...@@ -157,14 +158,6 @@ class CppGenerator : public BaseGenerator { ...@@ -157,14 +158,6 @@ class CppGenerator : public BaseGenerator {
code += name + ">(buf); }\n\n"; code += name + ">(buf); }\n\n";
} }
// The root verifier:
code += "inline bool Verify";
code += name;
code +=
"Buffer(flatbuffers::Verifier &verifier) { "
"return verifier.VerifyBuffer<";
code += cpp_qualified_name + ">(); }\n\n";
if (parser_.file_identifier_.length()) { if (parser_.file_identifier_.length()) {
// Return the identifier // Return the identifier
code += "inline const char *" + name; code += "inline const char *" + name;
...@@ -178,6 +171,20 @@ class CppGenerator : public BaseGenerator { ...@@ -178,6 +171,20 @@ class CppGenerator : public BaseGenerator {
code += name + "Identifier()); }\n\n"; code += name + "Identifier()); }\n\n";
} }
// The root verifier:
code += "inline bool Verify";
code += name;
code +=
"Buffer(flatbuffers::Verifier &verifier) { "
"return verifier.VerifyBuffer<";
code += cpp_qualified_name + ">(";
if (parser_.file_identifier_.length())
code += name + "Identifier()";
else
code += "nullptr";
code += "); }\n\n";
if (parser_.file_extension_.length()) { if (parser_.file_extension_.length()) {
// Return the extension // Return the extension
code += "inline const char *" + name; code += "inline const char *" + name;
...@@ -206,7 +213,7 @@ class CppGenerator : public BaseGenerator { ...@@ -206,7 +213,7 @@ class CppGenerator : public BaseGenerator {
private: private:
// This tracks the current namespace so we can insert namespace declarations. // This tracks the current namespace so we can insert namespace declarations.
const Namespace *cur_name_space_ = nullptr; const Namespace *cur_name_space_;
const Namespace *CurrentNameSpace() { return cur_name_space_; } const Namespace *CurrentNameSpace() { return cur_name_space_; }
...@@ -457,6 +464,30 @@ class CppGenerator : public BaseGenerator { ...@@ -457,6 +464,30 @@ class CppGenerator : public BaseGenerator {
: field.value.constant; : field.value.constant;
} }
void GenSimpleParam(std::string &code, FieldDef &field) {
code += ",\n " + GenTypeWire(field.value.type, " ", true);
code += field.name + " = ";
if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) {
auto ev = field.value.type.enum_def->ReverseLookup(
static_cast<int>(StringToInt(field.value.constant.c_str())),
false);
if (ev) {
code += WrapInNameSpace(
field.value.type.enum_def->defined_namespace,
GetEnumVal(*field.value.type.enum_def, *ev, parser_.opts));
}
else {
code += GenUnderlyingCast(field, true, field.value.constant);
}
}
else if (field.value.type.base_type == BASE_TYPE_BOOL) {
code += field.value.constant == "0" ? "false" : "true";
}
else {
code += GenDefaultConstant(field);
}
}
// Generate an accessor struct, builder structs & function for a table. // Generate an accessor struct, builder structs & function for a table.
void GenTable(StructDef &struct_def, std::string *code_ptr) { void GenTable(StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
...@@ -679,6 +710,7 @@ class CppGenerator : public BaseGenerator { ...@@ -679,6 +710,7 @@ class CppGenerator : public BaseGenerator {
// Generate a convenient CreateX function that uses the above builder // Generate a convenient CreateX function that uses the above builder
// to create a table in one go. // to create a table in one go.
bool gen_vector_pars = false;
code += "inline flatbuffers::Offset<" + struct_def.name + "> Create"; code += "inline flatbuffers::Offset<" + struct_def.name + "> Create";
code += struct_def.name; code += struct_def.name;
code += "(flatbuffers::FlatBufferBuilder &_fbb"; code += "(flatbuffers::FlatBufferBuilder &_fbb";
...@@ -686,24 +718,11 @@ class CppGenerator : public BaseGenerator { ...@@ -686,24 +718,11 @@ class CppGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
auto &field = **it; auto &field = **it;
if (!field.deprecated) { if (!field.deprecated) {
code += ",\n " + GenTypeWire(field.value.type, " ", true); if (field.value.type.base_type == BASE_TYPE_STRING ||
code += field.name + " = "; field.value.type.base_type == BASE_TYPE_VECTOR) {
if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) { gen_vector_pars = true;
auto ev = field.value.type.enum_def->ReverseLookup(
static_cast<int>(StringToInt(field.value.constant.c_str())),
false);
if (ev) {
code += WrapInNameSpace(
field.value.type.enum_def->defined_namespace,
GetEnumVal(*field.value.type.enum_def, *ev, parser_.opts));
} else {
code += GenUnderlyingCast(field, true, field.value.constant);
}
} else if (field.value.type.base_type == BASE_TYPE_BOOL) {
code += field.value.constant == "0" ? "false" : "true";
} else {
code += GenDefaultConstant(field);
} }
GenSimpleParam(code, field);
} }
} }
code += ") {\n " + struct_def.name + "Builder builder_(_fbb);\n"; code += ") {\n " + struct_def.name + "Builder builder_(_fbb);\n";
...@@ -719,6 +738,50 @@ class CppGenerator : public BaseGenerator { ...@@ -719,6 +738,50 @@ class CppGenerator : public BaseGenerator {
} }
} }
code += " return builder_.Finish();\n}\n\n"; code += " return builder_.Finish();\n}\n\n";
//Generate a CreateX function with vector types as parameters
if (gen_vector_pars) {
code += "inline flatbuffers::Offset<" + struct_def.name + "> Create";
code += struct_def.name;
code += "(flatbuffers::FlatBufferBuilder &_fbb";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (!field.deprecated) {
if (field.value.type.base_type == BASE_TYPE_STRING) {
code += ",\n const char *";
code += field.name + " = nullptr";
}
else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
code += ",\n const std::vector<";
code += GenTypeWire(field.value.type.VectorType(), "", false);
code += "> *" + field.name + " = nullptr";
} else {
GenSimpleParam(code, field);
}
}
}
code += ") {\n ";
code += "return Create";
code += struct_def.name;
code += "(_fbb";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (!field.deprecated) {
if (field.value.type.base_type == BASE_TYPE_STRING) {
code += ", " + field.name + " ? 0 : ";
code += "_fbb.CreateString(" + field.name + ")";
} else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
code += ", " + field.name + " ? 0 : ";
code += "_fbb.CreateVector<";
code += GenTypeWire(field.value.type.VectorType(), "", false);
code += ">(*" + field.name + ")";
} else code += ", " + field.name;
}
}
code += ");\n}\n\n";
}
} }
static void GenPadding(const FieldDef &field, std::string &code, static void GenPadding(const FieldDef &field, std::string &code,
......
...@@ -53,12 +53,14 @@ static void GenNameSpace(const Namespace &name_space, std::string *_schema, ...@@ -53,12 +53,14 @@ static void GenNameSpace(const Namespace &name_space, std::string *_schema,
// Generate a flatbuffer schema from the Parser's internal representation. // Generate a flatbuffer schema from the Parser's internal representation.
std::string GenerateFBS(const Parser &parser, const std::string &file_name) { std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
// Proto namespaces may clash with table names, so we have to prefix all: // Proto namespaces may clash with table names, so we have to prefix all:
for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end(); if (!parser.opts.escape_proto_identifiers) {
++it) { for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end();
for (auto comp = (*it)->components.begin(); comp != (*it)->components.end(); ++it) {
++comp) { for (auto comp = (*it)->components.begin(); comp != (*it)->components.end();
(*comp) = "_" + (*comp); ++comp) {
(*comp) = "_" + (*comp);
}
} }
} }
......
...@@ -193,8 +193,9 @@ class GeneralGenerator : public BaseGenerator { ...@@ -193,8 +193,9 @@ class GeneralGenerator : public BaseGenerator {
public: public:
GeneralGenerator(const Parser &parser, const std::string &path, GeneralGenerator(const Parser &parser, const std::string &path,
const std::string &file_name) const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "."){ : BaseGenerator(parser, path, file_name, "", "."),
assert(parser_.opts.lang <= IDLOptions::kMAX); lang_(language_parameters[parser_.opts.lang]) {
assert(parser_.opts.lang <= IDLOptions::kMAX);
}; };
bool generate() { bool generate() {
std::string one_file_code; std::string one_file_code;
...@@ -544,7 +545,7 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr) { ...@@ -544,7 +545,7 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr) {
// "too sparse". Change at will. // "too sparse". Change at will.
static const int kMaxSparseness = 5; static const int kMaxSparseness = 5;
if (range / static_cast<int64_t>(enum_def.vals.vec.size()) < kMaxSparseness) { if (range / static_cast<int64_t>(enum_def.vals.vec.size()) < kMaxSparseness) {
code += "\n private static"; code += "\n public static";
code += lang_.const_decl; code += lang_.const_decl;
code += lang_.string_type; code += lang_.string_type;
code += "[] names = { "; code += "[] names = { ";
...@@ -567,7 +568,10 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr) { ...@@ -567,7 +568,10 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr) {
} }
// Close the class // Close the class
code += "};\n\n"; 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. // Returns the function name that is able to read a value of the given type.
...@@ -1125,9 +1129,12 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) { ...@@ -1125,9 +1129,12 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "); }\n"; code += "); }\n";
} }
} }
code += "};\n\n"; code += "}";
// Java does not need the closing semi-colon on class definitions.
code += (lang_.language != IDLOptions::kJava) ? ";" : "";
code += "\n\n";
} }
const LanguageParameters & lang_ = language_parameters[parser_.opts.lang]; const LanguageParameters & lang_;
}; };
} // namespace general } // namespace general
......
...@@ -423,6 +423,12 @@ CheckedError Parser::Next() { ...@@ -423,6 +423,12 @@ CheckedError Parser::Next() {
return NoError(); return NoError();
} else if (isdigit(static_cast<unsigned char>(c)) || c == '-') { } else if (isdigit(static_cast<unsigned char>(c)) || c == '-') {
const char *start = cursor_ - 1; const char *start = cursor_ - 1;
if (c == '-' && *cursor_ == '0' && (cursor_[1] == 'x' || cursor_[1] == 'X')) {
++start;
++cursor_;
attribute_.append(&c, &c + 1);
c = '0';
}
if (c == '0' && (*cursor_ == 'x' || *cursor_ == 'X')) { if (c == '0' && (*cursor_ == 'x' || *cursor_ == 'X')) {
cursor_++; cursor_++;
while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++; while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++;
......
...@@ -162,7 +162,7 @@ struct TestSimpleTableWithEnumBuilder { ...@@ -162,7 +162,7 @@ struct TestSimpleTableWithEnumBuilder {
}; };
inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb,
Color color = Color_Green) { Color color = Color_Green) {
TestSimpleTableWithEnumBuilder builder_(_fbb); TestSimpleTableWithEnumBuilder builder_(_fbb);
builder_.add_color(color); builder_.add_color(color);
return builder_.Finish(); return builder_.Finish();
...@@ -205,9 +205,9 @@ struct StatBuilder { ...@@ -205,9 +205,9 @@ struct StatBuilder {
}; };
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> id = 0, flatbuffers::Offset<flatbuffers::String> id = 0,
int64_t val = 0, int64_t val = 0,
uint16_t count = 0) { uint16_t count = 0) {
StatBuilder builder_(_fbb); StatBuilder builder_(_fbb);
builder_.add_val(val); builder_.add_val(val);
builder_.add_id(id); builder_.add_id(id);
...@@ -215,6 +215,13 @@ inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb ...@@ -215,6 +215,13 @@ inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb
return builder_.Finish(); return builder_.Finish();
} }
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb,
const char *id = nullptr,
int64_t val = 0,
uint16_t count = 0) {
return CreateStat(_fbb, id ? 0 : _fbb.CreateString(id), val, count);
}
/// an example documentation comment: monster object /// an example documentation comment: monster object
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum { enum {
...@@ -397,34 +404,34 @@ struct MonsterBuilder { ...@@ -397,34 +404,34 @@ struct MonsterBuilder {
}; };
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
const Vec3 *pos = 0, const Vec3 *pos = 0,
int16_t mana = 150, int16_t mana = 150,
int16_t hp = 100, int16_t hp = 100,
flatbuffers::Offset<flatbuffers::String> name = 0, flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory = 0, flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory = 0,
Color color = Color_Blue, Color color = Color_Blue,
Any test_type = Any_NONE, Any test_type = Any_NONE,
flatbuffers::Offset<void> test = 0, flatbuffers::Offset<void> test = 0,
flatbuffers::Offset<flatbuffers::Vector<const Test *>> test4 = 0, flatbuffers::Offset<flatbuffers::Vector<const Test *>> test4 = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring = 0, flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Monster>>> testarrayoftables = 0, flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Monster>>> testarrayoftables = 0,
flatbuffers::Offset<Monster> enemy = 0, flatbuffers::Offset<Monster> enemy = 0,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> testnestedflatbuffer = 0, flatbuffers::Offset<flatbuffers::Vector<uint8_t>> testnestedflatbuffer = 0,
flatbuffers::Offset<Stat> testempty = 0, flatbuffers::Offset<Stat> testempty = 0,
bool testbool = false, bool testbool = false,
int32_t testhashs32_fnv1 = 0, int32_t testhashs32_fnv1 = 0,
uint32_t testhashu32_fnv1 = 0, uint32_t testhashu32_fnv1 = 0,
int64_t testhashs64_fnv1 = 0, int64_t testhashs64_fnv1 = 0,
uint64_t testhashu64_fnv1 = 0, uint64_t testhashu64_fnv1 = 0,
int32_t testhashs32_fnv1a = 0, int32_t testhashs32_fnv1a = 0,
uint32_t testhashu32_fnv1a = 0, uint32_t testhashu32_fnv1a = 0,
int64_t testhashs64_fnv1a = 0, int64_t testhashs64_fnv1a = 0,
uint64_t testhashu64_fnv1a = 0, uint64_t testhashu64_fnv1a = 0,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> testarrayofbools = 0, flatbuffers::Offset<flatbuffers::Vector<uint8_t>> testarrayofbools = 0,
float testf = 3.14159f, float testf = 3.14159f,
float testf2 = 3.0f, float testf2 = 3.0f,
float testf3 = 0.0f, float testf3 = 0.0f,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring2 = 0) { flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring2 = 0) {
MonsterBuilder builder_(_fbb); MonsterBuilder builder_(_fbb);
builder_.add_testhashu64_fnv1a(testhashu64_fnv1a); builder_.add_testhashu64_fnv1a(testhashu64_fnv1a);
builder_.add_testhashs64_fnv1a(testhashs64_fnv1a); builder_.add_testhashs64_fnv1a(testhashs64_fnv1a);
...@@ -457,6 +464,38 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder ...@@ -457,6 +464,38 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
return builder_.Finish(); return builder_.Finish();
} }
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
const Vec3 *pos = 0,
int16_t mana = 150,
int16_t hp = 100,
const char *name = nullptr,
const std::vector<uint8_t> *inventory = nullptr,
Color color = Color_Blue,
Any test_type = Any_NONE,
flatbuffers::Offset<void> test = 0,
const std::vector<const Test *> *test4 = nullptr,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *testarrayofstring = nullptr,
const std::vector<flatbuffers::Offset<Monster>> *testarrayoftables = nullptr,
flatbuffers::Offset<Monster> enemy = 0,
const std::vector<uint8_t> *testnestedflatbuffer = nullptr,
flatbuffers::Offset<Stat> testempty = 0,
bool testbool = false,
int32_t testhashs32_fnv1 = 0,
uint32_t testhashu32_fnv1 = 0,
int64_t testhashs64_fnv1 = 0,
uint64_t testhashu64_fnv1 = 0,
int32_t testhashs32_fnv1a = 0,
uint32_t testhashu32_fnv1a = 0,
int64_t testhashs64_fnv1a = 0,
uint64_t testhashu64_fnv1a = 0,
const std::vector<uint8_t> *testarrayofbools = nullptr,
float testf = 3.14159f,
float testf2 = 3.0f,
float testf3 = 0.0f,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *testarrayofstring2 = nullptr) {
return CreateMonster(_fbb, pos, mana, hp, name ? 0 : _fbb.CreateString(name), inventory ? 0 : _fbb.CreateVector<uint8_t>(*inventory), color, test_type, test, test4 ? 0 : _fbb.CreateVector<const Test *>(*test4), testarrayofstring ? 0 : _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*testarrayofstring), testarrayoftables ? 0 : _fbb.CreateVector<flatbuffers::Offset<Monster>>(*testarrayoftables), enemy, testnestedflatbuffer ? 0 : _fbb.CreateVector<uint8_t>(*testnestedflatbuffer), testempty, testbool, testhashs32_fnv1, testhashu32_fnv1, testhashs64_fnv1, testhashu64_fnv1, testhashs32_fnv1a, testhashu32_fnv1a, testhashs64_fnv1a, testhashu64_fnv1a, testarrayofbools ? 0 : _fbb.CreateVector<uint8_t>(*testarrayofbools), testf, testf2, testf3, testarrayofstring2 ? 0 : _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*testarrayofstring2));
}
inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *union_obj, Any type) { inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *union_obj, Any type) {
switch (type) { switch (type) {
case Any_NONE: return true; case Any_NONE: return true;
...@@ -471,12 +510,12 @@ inline const MyGame::Example::Monster *GetMonster(const void *buf) { return flat ...@@ -471,12 +510,12 @@ inline const MyGame::Example::Monster *GetMonster(const void *buf) { return flat
inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot<Monster>(buf); } inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot<Monster>(buf); }
inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Example::Monster>(); }
inline const char *MonsterIdentifier() { return "MONS"; } inline const char *MonsterIdentifier() { return "MONS"; }
inline bool MonsterBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, MonsterIdentifier()); } inline bool MonsterBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, MonsterIdentifier()); }
inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Example::Monster>(MonsterIdentifier()); }
inline const char *MonsterExtension() { return "mon"; } inline const char *MonsterExtension() { return "mon"; }
inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Example::Monster> root) { fbb.Finish(root, MonsterIdentifier()); } inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Example::Monster> root) { fbb.Finish(root, MonsterIdentifier()); }
......
...@@ -69,7 +69,7 @@ struct TableInNestedNSBuilder { ...@@ -69,7 +69,7 @@ struct TableInNestedNSBuilder {
}; };
inline flatbuffers::Offset<TableInNestedNS> CreateTableInNestedNS(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<TableInNestedNS> CreateTableInNestedNS(flatbuffers::FlatBufferBuilder &_fbb,
int32_t foo = 0) { int32_t foo = 0) {
TableInNestedNSBuilder builder_(_fbb); TableInNestedNSBuilder builder_(_fbb);
builder_.add_foo(foo); builder_.add_foo(foo);
return builder_.Finish(); return builder_.Finish();
......
...@@ -60,9 +60,9 @@ struct TableInFirstNSBuilder { ...@@ -60,9 +60,9 @@ struct TableInFirstNSBuilder {
}; };
inline flatbuffers::Offset<TableInFirstNS> CreateTableInFirstNS(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<TableInFirstNS> CreateTableInFirstNS(flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<NamespaceA::NamespaceB::TableInNestedNS> foo_table = 0, flatbuffers::Offset<NamespaceA::NamespaceB::TableInNestedNS> foo_table = 0,
NamespaceA::NamespaceB::EnumInNestedNS foo_enum = NamespaceA::NamespaceB::EnumInNestedNS_A, NamespaceA::NamespaceB::EnumInNestedNS foo_enum = NamespaceA::NamespaceB::EnumInNestedNS_A,
const NamespaceA::NamespaceB::StructInNestedNS *foo_struct = 0) { const NamespaceA::NamespaceB::StructInNestedNS *foo_struct = 0) {
TableInFirstNSBuilder builder_(_fbb); TableInFirstNSBuilder builder_(_fbb);
builder_.add_foo_struct(foo_struct); builder_.add_foo_struct(foo_struct);
builder_.add_foo_table(foo_table); builder_.add_foo_table(foo_table);
...@@ -107,8 +107,8 @@ struct TableInCBuilder { ...@@ -107,8 +107,8 @@ struct TableInCBuilder {
}; };
inline flatbuffers::Offset<TableInC> CreateTableInC(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<TableInC> CreateTableInC(flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<NamespaceA::TableInFirstNS> refer_to_a1 = 0, flatbuffers::Offset<NamespaceA::TableInFirstNS> refer_to_a1 = 0,
flatbuffers::Offset<NamespaceA::SecondTableInA> refer_to_a2 = 0) { flatbuffers::Offset<NamespaceA::SecondTableInA> refer_to_a2 = 0) {
TableInCBuilder builder_(_fbb); TableInCBuilder builder_(_fbb);
builder_.add_refer_to_a2(refer_to_a2); builder_.add_refer_to_a2(refer_to_a2);
builder_.add_refer_to_a1(refer_to_a1); builder_.add_refer_to_a1(refer_to_a1);
...@@ -146,7 +146,7 @@ struct SecondTableInABuilder { ...@@ -146,7 +146,7 @@ struct SecondTableInABuilder {
}; };
inline flatbuffers::Offset<SecondTableInA> CreateSecondTableInA(flatbuffers::FlatBufferBuilder &_fbb, inline flatbuffers::Offset<SecondTableInA> CreateSecondTableInA(flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<NamespaceC::TableInC> refer_to_c = 0) { flatbuffers::Offset<NamespaceC::TableInC> refer_to_c = 0) {
SecondTableInABuilder builder_(_fbb); SecondTableInABuilder builder_(_fbb);
builder_.add_refer_to_c(refer_to_c); builder_.add_refer_to_c(refer_to_c);
return builder_.Finish(); return builder_.Finish();
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
#define FLATBUFFERS_DEBUG_VERIFICATION_FAILURE 1 #define FLATBUFFERS_DEBUG_VERIFICATION_FAILURE 1
#define FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h" #include "flatbuffers/idl.h"
...@@ -160,6 +161,23 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length) { ...@@ -160,6 +161,23 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length) {
flatbuffers::Verifier verifier(flatbuf, length); flatbuffers::Verifier verifier(flatbuf, length);
TEST_EQ(VerifyMonsterBuffer(verifier), true); TEST_EQ(VerifyMonsterBuffer(verifier), true);
std::vector<uint8_t> test_buff;
test_buff.resize(length * 2);
std::memcpy(&test_buff[0], flatbuf , length);
std::memcpy(&test_buff[length], flatbuf , length);
flatbuffers::Verifier verifierl(&test_buff[0], length - 1);
TEST_EQ(VerifyMonsterBuffer(verifierl), false);
TEST_EQ(verifierl.GetComputedSize(), 0);
flatbuffers::Verifier verifier1(&test_buff[0], length);
TEST_EQ(VerifyMonsterBuffer(verifier1), true);
TEST_EQ(verifier1.GetComputedSize(), length);
flatbuffers::Verifier verifier2(&test_buff[length], length);
TEST_EQ(VerifyMonsterBuffer(verifier2), true);
TEST_EQ(verifier2.GetComputedSize(), length);
TEST_EQ(strcmp(MonsterIdentifier(), "MONS"), 0); TEST_EQ(strcmp(MonsterIdentifier(), "MONS"), 0);
TEST_EQ(MonsterBufferHasIdentifier(flatbuf), true); TEST_EQ(MonsterBufferHasIdentifier(flatbuf), true);
TEST_EQ(strcmp(MonsterExtension(), "mon"), 0); TEST_EQ(strcmp(MonsterExtension(), "mon"), 0);
...@@ -814,14 +832,14 @@ void ErrorTest() { ...@@ -814,14 +832,14 @@ void ErrorTest() {
TestError("table X { Y:byte; } root_type X; { Y:1, Y:2 }", "more than once"); TestError("table X { Y:byte; } root_type X; { Y:1, Y:2 }", "more than once");
} }
float TestValue(const char *json) { template<typename T> T TestValue(const char *json, const char *type_name) {
flatbuffers::Parser parser; flatbuffers::Parser parser;
// Simple schema. // Simple schema.
TEST_EQ(parser.Parse("table X { Y:float; } root_type X;"), true); TEST_EQ(parser.Parse(std::string("table X { Y:" + std::string(type_name) + "; } root_type X;").c_str()), true);
TEST_EQ(parser.Parse(json), true); TEST_EQ(parser.Parse(json), true);
auto root = flatbuffers::GetRoot<float>(parser.builder_.GetBufferPointer()); auto root = flatbuffers::GetRoot<T>(parser.builder_.GetBufferPointer());
// root will point to the table, which is a 32bit vtable offset followed // root will point to the table, which is a 32bit vtable offset followed
// by a float: // by a float:
TEST_EQ(sizeof(flatbuffers::soffset_t), 4); // Test assumes 32bit offsets TEST_EQ(sizeof(flatbuffers::soffset_t), 4); // Test assumes 32bit offsets
...@@ -833,10 +851,13 @@ bool FloatCompare(float a, float b) { return fabs(a - b) < 0.001; } ...@@ -833,10 +851,13 @@ bool FloatCompare(float a, float b) { return fabs(a - b) < 0.001; }
// Additional parser testing not covered elsewhere. // Additional parser testing not covered elsewhere.
void ValueTest() { void ValueTest() {
// Test scientific notation numbers. // Test scientific notation numbers.
TEST_EQ(FloatCompare(TestValue("{ Y:0.0314159e+2 }"), 3.14159), true); TEST_EQ(FloatCompare(TestValue<float>("{ Y:0.0314159e+2 }","float"), (float)3.14159), true);
// Test conversion functions. // Test conversion functions.
TEST_EQ(FloatCompare(TestValue("{ Y:cos(rad(180)) }"), -1), true); TEST_EQ(FloatCompare(TestValue<float>("{ Y:cos(rad(180)) }","float"), -1), true);
// Test negative hex constant.
TEST_EQ(TestValue<int>("{ Y:-0x80 }","int") == -128, true);
} }
void EnumStringsTest() { void EnumStringsTest() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment