mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-27 09:12:17 +00:00
Merge branch 'master' of https://github.com/google/flatbuffers
This commit is contained in:
@@ -33,11 +33,30 @@
|
|||||||
#if __cplusplus <= 199711L && \
|
#if __cplusplus <= 199711L && \
|
||||||
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
||||||
(!defined(__GNUC__) || \
|
(!defined(__GNUC__) || \
|
||||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40603))
|
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
|
||||||
#error A C++11 compatible compiler is required for FlatBuffers.
|
#error A C++11 compatible compiler with support for the auto typing is required for FlatBuffers.
|
||||||
#error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
|
#error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__clang__) && \
|
||||||
|
defined(__GNUC__) && \
|
||||||
|
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
|
||||||
|
// Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr and constexpr
|
||||||
|
// keywords. Note the __clang__ check is needed, because clang presents itself as an older GNUC
|
||||||
|
// compiler.
|
||||||
|
#ifndef nullptr_t
|
||||||
|
const class nullptr_t {
|
||||||
|
public:
|
||||||
|
template<class T> inline operator T*() const { return 0; }
|
||||||
|
private:
|
||||||
|
void operator&() const;
|
||||||
|
} nullptr = {};
|
||||||
|
#endif
|
||||||
|
#ifndef constexpr
|
||||||
|
#define constexpr const
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// The wire format uses a little endian encoding (since that's efficient for
|
// The wire format uses a little endian encoding (since that's efficient for
|
||||||
// the common platforms).
|
// the common platforms).
|
||||||
#if !defined(FLATBUFFERS_LITTLEENDIAN)
|
#if !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||||
@@ -154,7 +173,11 @@ template<typename T> size_t AlignOf() {
|
|||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return __alignof(T);
|
return __alignof(T);
|
||||||
#else
|
#else
|
||||||
return alignof(T);
|
#ifndef alignof
|
||||||
|
return __alignof__(T);
|
||||||
|
#else
|
||||||
|
return alignof(T);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,15 +859,20 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
|
|||||||
return CreateVectorOfStructs(v.data(), v.size());
|
return CreateVectorOfStructs(v.data(), v.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct TableKeyComparator {
|
||||||
|
TableKeyComparator(vector_downward& buf) : buf_(buf) {}
|
||||||
|
bool operator()(const Offset<T> &a, const Offset<T> &b) const {
|
||||||
|
auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
|
||||||
|
auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
|
||||||
|
return table_a->KeyCompareLessThan(table_b);
|
||||||
|
}
|
||||||
|
vector_downward& buf_;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
|
template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
|
||||||
Offset<T> *v, size_t len) {
|
Offset<T> *v, size_t len) {
|
||||||
std::sort(v, v + len,
|
std::sort(v, v + len, TableKeyComparator<T>(buf_));
|
||||||
[this](const Offset<T> &a, const Offset<T> &b) -> bool {
|
|
||||||
auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
|
|
||||||
auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
|
|
||||||
return table_a->KeyCompareLessThan(table_b);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return CreateVector(v, len);
|
return CreateVector(v, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -36,8 +38,8 @@ struct FnvTraits<uint32_t> {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct FnvTraits<uint64_t> {
|
struct FnvTraits<uint64_t> {
|
||||||
static const uint64_t kFnvPrime = 0x00000100000001b3;
|
static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
|
||||||
static const uint64_t kOffsetBasis = 0xcbf29ce484222645;
|
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@@ -444,6 +444,7 @@ private:
|
|||||||
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, int64_t *val);
|
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, int64_t *val);
|
||||||
FLATBUFFERS_CHECKED_ERROR Next();
|
FLATBUFFERS_CHECKED_ERROR Next();
|
||||||
|
FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
|
||||||
bool Is(int t);
|
bool Is(int t);
|
||||||
FLATBUFFERS_CHECKED_ERROR Expect(int t);
|
FLATBUFFERS_CHECKED_ERROR Expect(int t);
|
||||||
std::string TokenToStringId(int t);
|
std::string TokenToStringId(int t);
|
||||||
@@ -491,6 +492,10 @@ private:
|
|||||||
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
|
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
|
||||||
const char **include_paths,
|
const char **include_paths,
|
||||||
const char *source_filename);
|
const char *source_filename);
|
||||||
|
FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
|
||||||
|
StructDef *struct_def,
|
||||||
|
const char *suffix,
|
||||||
|
BaseType baseType);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SymbolTable<StructDef> structs_;
|
SymbolTable<StructDef> structs_;
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|
||||||
// Convert an integer or floating point value to a string.
|
// Convert an integer or floating point value to a string.
|
||||||
@@ -68,7 +70,7 @@ template<> inline std::string NumToString<double>(double t) {
|
|||||||
auto p = s.find_last_not_of('0');
|
auto p = s.find_last_not_of('0');
|
||||||
if (p != std::string::npos) {
|
if (p != std::string::npos) {
|
||||||
s.resize(p + 1); // Strip trailing zeroes.
|
s.resize(p + 1); // Strip trailing zeroes.
|
||||||
if (s.back() == '.')
|
if (s[s.size() - 1] == '.')
|
||||||
s.erase(s.size() - 1, 1); // Strip '.' if a whole number.
|
s.erase(s.size() - 1, 1); // Strip '.' if a whole number.
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
@@ -197,8 +199,8 @@ inline std::string StripFileName(const std::string &filepath) {
|
|||||||
inline std::string ConCatPathFileName(const std::string &path,
|
inline std::string ConCatPathFileName(const std::string &path,
|
||||||
const std::string &filename) {
|
const std::string &filename) {
|
||||||
std::string filepath = path;
|
std::string filepath = path;
|
||||||
if (path.length() && path.back() != kPathSeparator &&
|
if (path.length() && path[path.size() - 1] != kPathSeparator &&
|
||||||
path.back() != kPosixPathSeparator)
|
path[path.size() - 1] != kPosixPathSeparator)
|
||||||
filepath += kPathSeparator;
|
filepath += kPathSeparator;
|
||||||
filepath += filename;
|
filepath += filename;
|
||||||
return filepath;
|
return filepath;
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
VT_HP = 8,
|
VT_HP = 8,
|
||||||
VT_NAME = 10,
|
VT_NAME = 10,
|
||||||
VT_INVENTORY = 14,
|
VT_INVENTORY = 14,
|
||||||
VT_COLOR = 16,
|
VT_COLOR = 16
|
||||||
};
|
};
|
||||||
const Vec3 *pos() const { return GetStruct<const Vec3 *>(VT_POS); }
|
const Vec3 *pos() const { return GetStruct<const Vec3 *>(VT_POS); }
|
||||||
Vec3 *mutable_pos() { return GetStruct<Vec3 *>(VT_POS); }
|
Vec3 *mutable_pos() { return GetStruct<Vec3 *>(VT_POS); }
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "flatbuffers/flatbuffers.h"
|
#include "flatbuffers/flatbuffers.h"
|
||||||
#include "flatbuffers/idl.h"
|
#include "flatbuffers/idl.h"
|
||||||
#include "flatbuffers/util.h"
|
#include "flatbuffers/util.h"
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
static void Error(const std::string &err, bool usage = false,
|
static void Error(const std::string &err, bool usage = false,
|
||||||
bool show_exe_name = true);
|
bool show_exe_name = true);
|
||||||
|
|||||||
@@ -274,16 +274,24 @@ static void GenTable(const Parser &parser, StructDef &struct_def,
|
|||||||
// Generate field id constants.
|
// Generate field id constants.
|
||||||
if (struct_def.fields.vec.size() > 0) {
|
if (struct_def.fields.vec.size() > 0) {
|
||||||
code += " enum {\n";
|
code += " enum {\n";
|
||||||
|
bool is_first_field = true; // track the first field that's not deprecated
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
it != struct_def.fields.vec.end();
|
it != struct_def.fields.vec.end();
|
||||||
++it) {
|
++it) {
|
||||||
auto &field = **it;
|
auto &field = **it;
|
||||||
if (!field.deprecated) { // Deprecated fields won't be accessible.
|
if (!field.deprecated) { // Deprecated fields won't be accessible.
|
||||||
|
if (!is_first_field) {
|
||||||
|
// Add trailing comma and newline to previous element. Don't add trailing comma to
|
||||||
|
// last element since older versions of gcc complain about this.
|
||||||
|
code += ",\n";
|
||||||
|
} else {
|
||||||
|
is_first_field = false;
|
||||||
|
}
|
||||||
code += " " + GenFieldOffsetName(field) + " = ";
|
code += " " + GenFieldOffsetName(field) + " = ";
|
||||||
code += NumToString(field.value.offset) + ",\n";
|
code += NumToString(field.value.offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
code += " };\n";
|
code += "\n };\n";
|
||||||
}
|
}
|
||||||
// Generate the accessors.
|
// Generate the accessors.
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
@@ -520,15 +528,32 @@ static void GenTable(const Parser &parser, StructDef &struct_def,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void GenPadding(const FieldDef &field,
|
static void GenPadding(const FieldDef &field,
|
||||||
const std::function<void (int bits)> &f) {
|
std::string &code,
|
||||||
|
int &padding_id,
|
||||||
|
const std::function<void (int bits, std::string &code, int &padding_id)> &f) {
|
||||||
if (field.padding) {
|
if (field.padding) {
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
if (static_cast<int>(field.padding) & (1 << i))
|
if (static_cast<int>(field.padding) & (1 << i))
|
||||||
f((1 << i) * 8);
|
f((1 << i) * 8, code, padding_id);
|
||||||
assert(!(field.padding & ~0xF));
|
assert(!(field.padding & ~0xF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PaddingDefinition(int bits, std::string &code, int &padding_id) {
|
||||||
|
code += " int" + NumToString(bits) +
|
||||||
|
"_t __padding" + NumToString(padding_id++) + ";\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PaddingDeclaration(int bits, std::string &code, int &padding_id) {
|
||||||
|
(void)bits;
|
||||||
|
code += " (void)__padding" + NumToString(padding_id++) + ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PaddingInitializer(int bits, std::string &code, int &padding_id) {
|
||||||
|
(void)bits;
|
||||||
|
code += ", __padding" + NumToString(padding_id++) + "(0)";
|
||||||
|
}
|
||||||
|
|
||||||
// Generate an accessor struct with constructor for a flatbuffers struct.
|
// Generate an accessor struct with constructor for a flatbuffers struct.
|
||||||
static void GenStruct(const Parser &parser, StructDef &struct_def,
|
static void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||||
std::string *code_ptr) {
|
std::string *code_ptr) {
|
||||||
@@ -550,10 +575,7 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
|
|||||||
auto &field = **it;
|
auto &field = **it;
|
||||||
code += " " + GenTypeGet(parser, field.value.type, " ", "", " ", false);
|
code += " " + GenTypeGet(parser, field.value.type, " ", "", " ", false);
|
||||||
code += field.name + "_;\n";
|
code += field.name + "_;\n";
|
||||||
GenPadding(field, [&code, &padding_id](int bits) {
|
GenPadding(field, code, padding_id, PaddingDefinition);
|
||||||
code += " int" + NumToString(bits) +
|
|
||||||
"_t __padding" + NumToString(padding_id++) + ";\n";
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a constructor that takes all fields as arguments.
|
// Generate a constructor that takes all fields as arguments.
|
||||||
@@ -581,21 +603,16 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
|
|||||||
} else {
|
} else {
|
||||||
code += "_" + field.name + ")";
|
code += "_" + field.name + ")";
|
||||||
}
|
}
|
||||||
GenPadding(field, [&code, &padding_id](int bits) {
|
GenPadding(field, code, padding_id, PaddingInitializer);
|
||||||
(void)bits;
|
|
||||||
code += ", __padding" + NumToString(padding_id++) + "(0)";
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code += " {";
|
code += " {";
|
||||||
padding_id = 0;
|
padding_id = 0;
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
it != struct_def.fields.vec.end();
|
it != struct_def.fields.vec.end();
|
||||||
++it) {
|
++it) {
|
||||||
auto &field = **it;
|
auto &field = **it;
|
||||||
GenPadding(field, [&code, &padding_id](int bits) {
|
GenPadding(field, code, padding_id, PaddingDeclaration);
|
||||||
(void)bits;
|
|
||||||
code += " (void)__padding" + NumToString(padding_id++) + ";";
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
code += " }\n\n";
|
code += " }\n\n";
|
||||||
|
|
||||||
@@ -649,6 +666,12 @@ void CloseNestedNameSpaces(Namespace *ns, std::string *code_ptr) {
|
|||||||
|
|
||||||
} // namespace cpp
|
} // namespace cpp
|
||||||
|
|
||||||
|
struct IsAlnum {
|
||||||
|
bool operator()(char c) {
|
||||||
|
return !isalnum(c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Iterate through all definitions we haven't generate code for (enums, structs,
|
// Iterate through all definitions we haven't generate code for (enums, structs,
|
||||||
// and tables) and output them to a single file.
|
// and tables) and output them to a single file.
|
||||||
std::string GenerateCPP(const Parser &parser,
|
std::string GenerateCPP(const Parser &parser,
|
||||||
@@ -719,7 +742,7 @@ std::string GenerateCPP(const Parser &parser,
|
|||||||
include_guard_ident.erase(
|
include_guard_ident.erase(
|
||||||
std::remove_if(include_guard_ident.begin(),
|
std::remove_if(include_guard_ident.begin(),
|
||||||
include_guard_ident.end(),
|
include_guard_ident.end(),
|
||||||
[](char c) { return !isalnum(c); }),
|
IsAlnum()),
|
||||||
include_guard_ident.end());
|
include_guard_ident.end());
|
||||||
std::string include_guard = "FLATBUFFERS_GENERATED_" + include_guard_ident;
|
std::string include_guard = "FLATBUFFERS_GENERATED_" + include_guard_ident;
|
||||||
include_guard += "_";
|
include_guard += "_";
|
||||||
|
|||||||
@@ -876,7 +876,27 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// generate object accessors if is nested_flatbuffer
|
||||||
|
auto nested = field.attributes.Lookup("nested_flatbuffer");
|
||||||
|
if (nested) {
|
||||||
|
auto nested_qualified_name =
|
||||||
|
parser.namespaces_.back()->GetFullyQualifiedName(nested->constant);
|
||||||
|
auto nested_type = parser.structs_.Lookup(nested_qualified_name);
|
||||||
|
auto nested_type_name = WrapInNameSpace(parser, *nested_type);
|
||||||
|
auto nestedMethodName = MakeCamel(field.name, lang.first_camel_upper)
|
||||||
|
+ "As" + nested_type_name;
|
||||||
|
auto getNestedMethodName = nestedMethodName;
|
||||||
|
if (lang.language == IDLOptions::kCSharp) {
|
||||||
|
getNestedMethodName = "Get" + nestedMethodName;
|
||||||
|
}
|
||||||
|
code += " public " + nested_type_name + " ";
|
||||||
|
code += nestedMethodName + "() { return ";
|
||||||
|
code += getNestedMethodName + "(new " + nested_type_name + "()); }\n";
|
||||||
|
code += " public " + nested_type_name + " " + getNestedMethodName;
|
||||||
|
code += "(" + nested_type_name + " obj) { ";
|
||||||
|
code += "int o = __offset(" + NumToString(field.value.offset) +"); ";
|
||||||
|
code += "return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; }\n";
|
||||||
|
}
|
||||||
// generate mutators for scalar fields or vectors of scalars
|
// generate mutators for scalar fields or vectors of scalars
|
||||||
if (parser.opts.mutable_buffer) {
|
if (parser.opts.mutable_buffer) {
|
||||||
auto underlying_type = field.value.type.base_type == BASE_TYPE_VECTOR
|
auto underlying_type = field.value.type.base_type == BASE_TYPE_VECTOR
|
||||||
|
|||||||
@@ -201,6 +201,14 @@ CheckedError Parser::ParseHexNum(int nibbles, int64_t *val) {
|
|||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckedError Parser::SkipByteOrderMark() {
|
||||||
|
if (static_cast<unsigned char>(*cursor_) != 0xef) return NoError();
|
||||||
|
cursor_++;
|
||||||
|
if (static_cast<unsigned char>(*cursor_++) != 0xbb) return Error("invalid utf-8 byte order mark");
|
||||||
|
if (static_cast<unsigned char>(*cursor_++) != 0xbf) return Error("invalid utf-8 byte order mark");
|
||||||
|
return NoError();
|
||||||
|
}
|
||||||
|
|
||||||
CheckedError Parser::Next() {
|
CheckedError Parser::Next() {
|
||||||
doc_comment_.clear();
|
doc_comment_.clear();
|
||||||
bool seen_newline = false;
|
bool seen_newline = false;
|
||||||
@@ -1118,6 +1126,33 @@ CheckedError Parser::StartStruct(const std::string &name, StructDef **dest) {
|
|||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckedError Parser::CheckClash(std::vector<FieldDef*> &fields,
|
||||||
|
StructDef *struct_def,
|
||||||
|
const char *suffix,
|
||||||
|
BaseType basetype) {
|
||||||
|
auto len = strlen(suffix);
|
||||||
|
for (auto it = fields.begin(); it != fields.end(); ++it) {
|
||||||
|
auto &fname = (*it)->name;
|
||||||
|
if (fname.length() > len &&
|
||||||
|
fname.compare(fname.length() - len, len, suffix) == 0 &&
|
||||||
|
(*it)->value.type.base_type != BASE_TYPE_UTYPE) {
|
||||||
|
auto field = struct_def->fields.Lookup(
|
||||||
|
fname.substr(0, fname.length() - len));
|
||||||
|
if (field && field->value.type.base_type == basetype)
|
||||||
|
return Error("Field " + fname +
|
||||||
|
" would clash with generated functions for field " +
|
||||||
|
field->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NoError();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool compareFieldDefs(const FieldDef *a, const FieldDef *b) {
|
||||||
|
auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str());
|
||||||
|
auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str());
|
||||||
|
return a_id < b_id;
|
||||||
|
}
|
||||||
|
|
||||||
CheckedError Parser::ParseDecl() {
|
CheckedError Parser::ParseDecl() {
|
||||||
std::vector<std::string> dc = doc_comment_;
|
std::vector<std::string> dc = doc_comment_;
|
||||||
bool fixed = Is(kTokenStruct);
|
bool fixed = Is(kTokenStruct);
|
||||||
@@ -1160,12 +1195,7 @@ CheckedError Parser::ParseDecl() {
|
|||||||
"either all fields or no fields must have an 'id' attribute");
|
"either all fields or no fields must have an 'id' attribute");
|
||||||
// Simply sort by id, then the fields are the same as if no ids had
|
// Simply sort by id, then the fields are the same as if no ids had
|
||||||
// been specified.
|
// been specified.
|
||||||
std::sort(fields.begin(), fields.end(),
|
std::sort(fields.begin(), fields.end(), compareFieldDefs);
|
||||||
[](const FieldDef *a, const FieldDef *b) -> bool {
|
|
||||||
auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str());
|
|
||||||
auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str());
|
|
||||||
return a_id < b_id;
|
|
||||||
});
|
|
||||||
// Verify we have a contiguous set, and reassign vtable offsets.
|
// Verify we have a contiguous set, and reassign vtable offsets.
|
||||||
for (int i = 0; i < static_cast<int>(fields.size()); i++) {
|
for (int i = 0; i < static_cast<int>(fields.size()); i++) {
|
||||||
if (i != atoi(fields[i]->attributes.Lookup("id")->constant.c_str()))
|
if (i != atoi(fields[i]->attributes.Lookup("id")->constant.c_str()))
|
||||||
@@ -1175,34 +1205,13 @@ CheckedError Parser::ParseDecl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check that no identifiers clash with auto generated fields.
|
|
||||||
// This is not an ideal situation, but should occur very infrequently,
|
ECHECK(CheckClash(fields, struct_def, "_type", BASE_TYPE_UNION));
|
||||||
// and allows us to keep using very readable names for type & length fields
|
ECHECK(CheckClash(fields, struct_def, "Type", BASE_TYPE_UNION));
|
||||||
// without inducing compile errors.
|
ECHECK(CheckClash(fields, struct_def, "_length", BASE_TYPE_VECTOR));
|
||||||
auto CheckClash = [&fields, &struct_def, this](const char *suffix,
|
ECHECK(CheckClash(fields, struct_def, "Length", BASE_TYPE_VECTOR));
|
||||||
BaseType basetype) -> CheckedError {
|
ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING));
|
||||||
auto len = strlen(suffix);
|
ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING));
|
||||||
for (auto it = fields.begin(); it != fields.end(); ++it) {
|
|
||||||
auto &fname = (*it)->name;
|
|
||||||
if (fname.length() > len &&
|
|
||||||
fname.compare(fname.length() - len, len, suffix) == 0 &&
|
|
||||||
(*it)->value.type.base_type != BASE_TYPE_UTYPE) {
|
|
||||||
auto field = struct_def->fields.Lookup(
|
|
||||||
fname.substr(0, fname.length() - len));
|
|
||||||
if (field && field->value.type.base_type == basetype)
|
|
||||||
return Error("Field " + fname +
|
|
||||||
" would clash with generated functions for field " +
|
|
||||||
field->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NoError();
|
|
||||||
};
|
|
||||||
ECHECK(CheckClash("_type", BASE_TYPE_UNION));
|
|
||||||
ECHECK(CheckClash("Type", BASE_TYPE_UNION));
|
|
||||||
ECHECK(CheckClash("_length", BASE_TYPE_VECTOR));
|
|
||||||
ECHECK(CheckClash("Length", BASE_TYPE_VECTOR));
|
|
||||||
ECHECK(CheckClash("_byte_vector", BASE_TYPE_STRING));
|
|
||||||
ECHECK(CheckClash("ByteVector", BASE_TYPE_STRING));
|
|
||||||
EXPECT('}');
|
EXPECT('}');
|
||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
@@ -1244,6 +1253,10 @@ CheckedError Parser::ParseNamespace() {
|
|||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool compareEnumVals(const EnumVal *a, const EnumVal* b) {
|
||||||
|
return a->value < b->value;
|
||||||
|
}
|
||||||
|
|
||||||
// Best effort parsing of .proto declarations, with the aim to turn them
|
// Best effort parsing of .proto declarations, with the aim to turn them
|
||||||
// in the closest corresponding FlatBuffer equivalent.
|
// in the closest corresponding FlatBuffer equivalent.
|
||||||
// We parse everything as identifiers instead of keywords, since we don't
|
// We parse everything as identifiers instead of keywords, since we don't
|
||||||
@@ -1294,9 +1307,8 @@ CheckedError Parser::ParseProtoDecl() {
|
|||||||
if (Is(';')) NEXT();
|
if (Is(';')) NEXT();
|
||||||
// Protobuf allows them to be specified in any order, so sort afterwards.
|
// Protobuf allows them to be specified in any order, so sort afterwards.
|
||||||
auto &v = enum_def->vals.vec;
|
auto &v = enum_def->vals.vec;
|
||||||
std::sort(v.begin(), v.end(), [](const EnumVal *a, const EnumVal *b) {
|
std::sort(v.begin(), v.end(), compareEnumVals);
|
||||||
return a->value < b->value;
|
|
||||||
});
|
|
||||||
// Temp: remove any duplicates, as .fbs files can't handle them.
|
// Temp: remove any duplicates, as .fbs files can't handle them.
|
||||||
for (auto it = v.begin(); it != v.end(); ) {
|
for (auto it = v.begin(); it != v.end(); ) {
|
||||||
if (it != v.begin() && it[0]->value == it[-1]->value) it = v.erase(it);
|
if (it != v.begin() && it[0]->value == it[-1]->value) it = v.erase(it);
|
||||||
@@ -1593,6 +1605,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
|||||||
builder_.Clear();
|
builder_.Clear();
|
||||||
// Start with a blank namespace just in case this file doesn't have one.
|
// Start with a blank namespace just in case this file doesn't have one.
|
||||||
namespaces_.push_back(new Namespace());
|
namespaces_.push_back(new Namespace());
|
||||||
|
ECHECK(SkipByteOrderMark());
|
||||||
NEXT();
|
NEXT();
|
||||||
// Includes must come before type declarations:
|
// Includes must come before type declarations:
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -1744,11 +1757,14 @@ std::set<std::string> Parser::GetIncludedFilesRecursive(
|
|||||||
|
|
||||||
// Schema serialization functionality:
|
// Schema serialization functionality:
|
||||||
|
|
||||||
|
template<typename T> bool compareName(const T* a, const T* b) {
|
||||||
|
return a->name < b->name;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> void AssignIndices(const std::vector<T *> &defvec) {
|
template<typename T> void AssignIndices(const std::vector<T *> &defvec) {
|
||||||
// Pre-sort these vectors, such that we can set the correct indices for them.
|
// Pre-sort these vectors, such that we can set the correct indices for them.
|
||||||
auto vec = defvec;
|
auto vec = defvec;
|
||||||
std::sort(vec.begin(), vec.end(),
|
std::sort(vec.begin(), vec.end(), compareName<T>);
|
||||||
[](const T *a, const T *b) { return a->name < b->name; });
|
|
||||||
for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i;
|
for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -215,5 +215,44 @@ namespace FlatBuffers.Test
|
|||||||
Assert.AreEqual("NONE", Any.NONE.ToString());
|
Assert.AreEqual("NONE", Any.NONE.ToString());
|
||||||
Assert.AreEqual("Monster", Any.Monster.ToString());
|
Assert.AreEqual("Monster", Any.Monster.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[FlatBuffersTestMethod]
|
||||||
|
public void TestNestedFlatBuffer()
|
||||||
|
{
|
||||||
|
const string nestedMonsterName = "NestedMonsterName";
|
||||||
|
const short nestedMonsterHp = 600;
|
||||||
|
const short nestedMonsterMana = 1024;
|
||||||
|
// Create nested buffer as a Monster type
|
||||||
|
var fbb1 = new FlatBufferBuilder(16);
|
||||||
|
var str1 = fbb1.CreateString(nestedMonsterName);
|
||||||
|
Monster.StartMonster(fbb1);
|
||||||
|
Monster.AddName(fbb1, str1);
|
||||||
|
Monster.AddHp(fbb1, nestedMonsterHp);
|
||||||
|
Monster.AddMana(fbb1, nestedMonsterMana);
|
||||||
|
var monster1 = Monster.EndMonster(fbb1);
|
||||||
|
Monster.FinishMonsterBuffer(fbb1, monster1);
|
||||||
|
var fbb1Bytes = fbb1.SizedByteArray();
|
||||||
|
fbb1 = null;
|
||||||
|
|
||||||
|
// Create a Monster which has the first buffer as a nested buffer
|
||||||
|
var fbb2 = new FlatBufferBuilder(16);
|
||||||
|
var str2 = fbb2.CreateString("My Monster");
|
||||||
|
var nestedBuffer = Monster.CreateTestnestedflatbufferVector(fbb2, fbb1Bytes);
|
||||||
|
Monster.StartMonster(fbb2);
|
||||||
|
Monster.AddName(fbb2, str2);
|
||||||
|
Monster.AddHp(fbb2, 50);
|
||||||
|
Monster.AddMana(fbb2, 32);
|
||||||
|
Monster.AddTestnestedflatbuffer(fbb2, nestedBuffer);
|
||||||
|
var monster = Monster.EndMonster(fbb2);
|
||||||
|
Monster.FinishMonsterBuffer(fbb2, monster);
|
||||||
|
|
||||||
|
// Now test the data extracted from the nested buffer
|
||||||
|
var mons = Monster.GetRootAsMonster(fbb2.DataBuffer);
|
||||||
|
var nestedMonster = mons.TestnestedflatbufferAsMonster();
|
||||||
|
|
||||||
|
Assert.AreEqual(nestedMonsterMana, nestedMonster.Mana);
|
||||||
|
Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp);
|
||||||
|
Assert.AreEqual(nestedMonsterName, nestedMonster.Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,6 +159,8 @@ class JavaTest {
|
|||||||
|
|
||||||
TestNamespaceNesting();
|
TestNamespaceNesting();
|
||||||
|
|
||||||
|
TestNestedFlatBuffer();
|
||||||
|
|
||||||
System.out.println("FlatBuffers test: completed successfully");
|
System.out.println("FlatBuffers test: completed successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +245,42 @@ class JavaTest {
|
|||||||
int off = TableInFirstNS.endTableInFirstNS(fbb);
|
int off = TableInFirstNS.endTableInFirstNS(fbb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TestNestedFlatBuffer() {
|
||||||
|
final String nestedMonsterName = "NestedMonsterName";
|
||||||
|
final short nestedMonsterHp = 600;
|
||||||
|
final short nestedMonsterMana = 1024;
|
||||||
|
|
||||||
|
FlatBufferBuilder fbb1 = new FlatBufferBuilder(16);
|
||||||
|
int str1 = fbb1.createString(nestedMonsterName);
|
||||||
|
Monster.startMonster(fbb1);
|
||||||
|
Monster.addName(fbb1, str1);
|
||||||
|
Monster.addHp(fbb1, nestedMonsterHp);
|
||||||
|
Monster.addMana(fbb1, nestedMonsterMana);
|
||||||
|
int monster1 = Monster.endMonster(fbb1);
|
||||||
|
Monster.finishMonsterBuffer(fbb1, monster1);
|
||||||
|
byte[] fbb1Bytes = fbb1.sizedByteArray();
|
||||||
|
fbb1 = null;
|
||||||
|
|
||||||
|
FlatBufferBuilder fbb2 = new FlatBufferBuilder(16);
|
||||||
|
int str2 = fbb2.createString("My Monster");
|
||||||
|
int nestedBuffer = Monster.createTestnestedflatbufferVector(fbb2, fbb1Bytes);
|
||||||
|
Monster.startMonster(fbb2);
|
||||||
|
Monster.addName(fbb2, str2);
|
||||||
|
Monster.addHp(fbb2, (short)50);
|
||||||
|
Monster.addMana(fbb2, (short)32);
|
||||||
|
Monster.addTestnestedflatbuffer(fbb2, nestedBuffer);
|
||||||
|
int monster = Monster.endMonster(fbb2);
|
||||||
|
Monster.finishMonsterBuffer(fbb2, monster);
|
||||||
|
|
||||||
|
// Now test the data extracted from the nested buffer
|
||||||
|
Monster mons = Monster.getRootAsMonster(fbb2.dataBuffer());
|
||||||
|
Monster nestedMonster = mons.testnestedflatbufferAsMonster();
|
||||||
|
|
||||||
|
TestEq(nestedMonsterMana, nestedMonster.mana());
|
||||||
|
TestEq(nestedMonsterHp, nestedMonster.hp());
|
||||||
|
TestEq(nestedMonsterName, nestedMonster.name());
|
||||||
|
}
|
||||||
|
|
||||||
static <T> void TestEq(T a, T b) {
|
static <T> void TestEq(T a, T b) {
|
||||||
if (!a.equals(b)) {
|
if (!a.equals(b)) {
|
||||||
System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
|
System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ public sealed class Monster : Table {
|
|||||||
public byte GetTestnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
|
public byte GetTestnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
|
||||||
public int TestnestedflatbufferLength { get { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } }
|
public int TestnestedflatbufferLength { get { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } }
|
||||||
public ArraySegment<byte>? GetTestnestedflatbufferBytes() { return __vector_as_arraysegment(30); }
|
public ArraySegment<byte>? GetTestnestedflatbufferBytes() { return __vector_as_arraysegment(30); }
|
||||||
|
public Monster TestnestedflatbufferAsMonster() { return GetTestnestedflatbufferAsMonster(new Monster()); }
|
||||||
|
public Monster GetTestnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; }
|
||||||
public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.Put(__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } }
|
public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.Put(__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } }
|
||||||
public Stat Testempty { get { return GetTestempty(new Stat()); } }
|
public Stat Testempty { get { return GetTestempty(new Stat()); } }
|
||||||
public Stat GetTestempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
|
public Stat GetTestempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ public final class Monster extends Table {
|
|||||||
public int testnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; }
|
public int testnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; }
|
||||||
public int testnestedflatbufferLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; }
|
public int testnestedflatbufferLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; }
|
||||||
public ByteBuffer testnestedflatbufferAsByteBuffer() { return __vector_as_bytebuffer(30, 1); }
|
public ByteBuffer testnestedflatbufferAsByteBuffer() { return __vector_as_bytebuffer(30, 1); }
|
||||||
|
public Monster testnestedflatbufferAsMonster() { return testnestedflatbufferAsMonster(new Monster()); }
|
||||||
|
public Monster testnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; }
|
||||||
public boolean mutateTestnestedflatbuffer(int j, int testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.put(__vector(o) + j * 1, (byte)testnestedflatbuffer); return true; } else { return false; } }
|
public boolean mutateTestnestedflatbuffer(int j, int testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.put(__vector(o) + j * 1, (byte)testnestedflatbuffer); return true; } else { return false; } }
|
||||||
public Stat testempty() { return testempty(new Stat()); }
|
public Stat testempty() { return testempty(new Stat()); }
|
||||||
public Stat testempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
|
public Stat testempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ STRUCT_END(Vec3, 32);
|
|||||||
|
|
||||||
struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
enum {
|
enum {
|
||||||
VT_COLOR = 4,
|
VT_COLOR = 4
|
||||||
};
|
};
|
||||||
Color color() const { return static_cast<Color>(GetField<int8_t>(VT_COLOR, 2)); }
|
Color color() const { return static_cast<Color>(GetField<int8_t>(VT_COLOR, 2)); }
|
||||||
bool mutate_color(Color _color) { return SetField(VT_COLOR, static_cast<int8_t>(_color)); }
|
bool mutate_color(Color _color) { return SetField(VT_COLOR, static_cast<int8_t>(_color)); }
|
||||||
@@ -136,7 +136,7 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
enum {
|
enum {
|
||||||
VT_ID = 4,
|
VT_ID = 4,
|
||||||
VT_VAL = 6,
|
VT_VAL = 6,
|
||||||
VT_COUNT = 8,
|
VT_COUNT = 8
|
||||||
};
|
};
|
||||||
const flatbuffers::String *id() const { return GetPointer<const flatbuffers::String *>(VT_ID); }
|
const flatbuffers::String *id() const { return GetPointer<const flatbuffers::String *>(VT_ID); }
|
||||||
flatbuffers::String *mutable_id() { return GetPointer<flatbuffers::String *>(VT_ID); }
|
flatbuffers::String *mutable_id() { return GetPointer<flatbuffers::String *>(VT_ID); }
|
||||||
@@ -205,7 +205,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
VT_TESTHASHU32_FNV1A = 46,
|
VT_TESTHASHU32_FNV1A = 46,
|
||||||
VT_TESTHASHS64_FNV1A = 48,
|
VT_TESTHASHS64_FNV1A = 48,
|
||||||
VT_TESTHASHU64_FNV1A = 50,
|
VT_TESTHASHU64_FNV1A = 50,
|
||||||
VT_TESTARRAYOFBOOLS = 52,
|
VT_TESTARRAYOFBOOLS = 52
|
||||||
};
|
};
|
||||||
const Vec3 *pos() const { return GetStruct<const Vec3 *>(VT_POS); }
|
const Vec3 *pos() const { return GetStruct<const Vec3 *>(VT_POS); }
|
||||||
Vec3 *mutable_pos() { return GetStruct<Vec3 *>(VT_POS); }
|
Vec3 *mutable_pos() { return GetStruct<Vec3 *>(VT_POS); }
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ STRUCT_END(StructInNestedNS, 8);
|
|||||||
|
|
||||||
struct TableInNestedNS FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct TableInNestedNS FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
enum {
|
enum {
|
||||||
VT_FOO = 4,
|
VT_FOO = 4
|
||||||
};
|
};
|
||||||
int32_t foo() const { return GetField<int32_t>(VT_FOO, 0); }
|
int32_t foo() const { return GetField<int32_t>(VT_FOO, 0); }
|
||||||
bool mutate_foo(int32_t _foo) { return SetField(VT_FOO, _foo); }
|
bool mutate_foo(int32_t _foo) { return SetField(VT_FOO, _foo); }
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ struct TableInFirstNS FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
enum {
|
enum {
|
||||||
VT_FOO_TABLE = 4,
|
VT_FOO_TABLE = 4,
|
||||||
VT_FOO_ENUM = 6,
|
VT_FOO_ENUM = 6,
|
||||||
VT_FOO_STRUCT = 8,
|
VT_FOO_STRUCT = 8
|
||||||
};
|
};
|
||||||
const NamespaceA::NamespaceB::TableInNestedNS *foo_table() const { return GetPointer<const NamespaceA::NamespaceB::TableInNestedNS *>(VT_FOO_TABLE); }
|
const NamespaceA::NamespaceB::TableInNestedNS *foo_table() const { return GetPointer<const NamespaceA::NamespaceB::TableInNestedNS *>(VT_FOO_TABLE); }
|
||||||
NamespaceA::NamespaceB::TableInNestedNS *mutable_foo_table() { return GetPointer<NamespaceA::NamespaceB::TableInNestedNS *>(VT_FOO_TABLE); }
|
NamespaceA::NamespaceB::TableInNestedNS *mutable_foo_table() { return GetPointer<NamespaceA::NamespaceB::TableInNestedNS *>(VT_FOO_TABLE); }
|
||||||
|
|||||||
@@ -478,8 +478,8 @@ void FuzzTest1() {
|
|||||||
const uint16_t ushort_val = 0xFEEE;
|
const uint16_t ushort_val = 0xFEEE;
|
||||||
const int32_t int_val = 0x83333333;
|
const int32_t int_val = 0x83333333;
|
||||||
const uint32_t uint_val = 0xFDDDDDDD;
|
const uint32_t uint_val = 0xFDDDDDDD;
|
||||||
const int64_t long_val = 0x8444444444444444;
|
const int64_t long_val = 0x8444444444444444LL;
|
||||||
const uint64_t ulong_val = 0xFCCCCCCCCCCCCCCC;
|
const uint64_t ulong_val = 0xFCCCCCCCCCCCCCCCULL;
|
||||||
const float float_val = 3.14159f;
|
const float float_val = 3.14159f;
|
||||||
const double double_val = 3.14159265359;
|
const double double_val = 3.14159265359;
|
||||||
|
|
||||||
@@ -564,8 +564,28 @@ void FuzzTest2() {
|
|||||||
|
|
||||||
struct RndDef {
|
struct RndDef {
|
||||||
std::string instances[instances_per_definition];
|
std::string instances[instances_per_definition];
|
||||||
|
|
||||||
|
// Since we're generating schema and corresponding data in tandem,
|
||||||
|
// this convenience function adds strings to both at once.
|
||||||
|
static void Add(RndDef (&definitions_l)[num_definitions],
|
||||||
|
std::string &schema_l,
|
||||||
|
const int instances_per_definition_l,
|
||||||
|
const char *schema_add, const char *instance_add,
|
||||||
|
int definition) {
|
||||||
|
schema_l += schema_add;
|
||||||
|
for (int i = 0; i < instances_per_definition_l; i++)
|
||||||
|
definitions_l[definition].instances[i] += instance_add;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define AddToSchemaAndInstances(schema_add, instance_add) \
|
||||||
|
RndDef::Add(definitions, schema, instances_per_definition, \
|
||||||
|
schema_add, instance_add, definition)
|
||||||
|
|
||||||
|
#define Dummy() \
|
||||||
|
RndDef::Add(definitions, schema, instances_per_definition, \
|
||||||
|
"byte", "1", definition)
|
||||||
|
|
||||||
RndDef definitions[num_definitions];
|
RndDef definitions[num_definitions];
|
||||||
|
|
||||||
// We are going to generate num_definitions, the first
|
// We are going to generate num_definitions, the first
|
||||||
@@ -577,17 +597,6 @@ void FuzzTest2() {
|
|||||||
// being generated. We generate multiple instances such that when creating
|
// being generated. We generate multiple instances such that when creating
|
||||||
// hierarchy, we get some variety by picking one randomly.
|
// hierarchy, we get some variety by picking one randomly.
|
||||||
for (int definition = 0; definition < num_definitions; definition++) {
|
for (int definition = 0; definition < num_definitions; definition++) {
|
||||||
// Since we're generating schema & and corresponding data in tandem,
|
|
||||||
// this convenience function adds strings to both at once.
|
|
||||||
auto AddToSchemaAndInstances = [&](const char *schema_add,
|
|
||||||
const char *instance_add) {
|
|
||||||
schema += schema_add;
|
|
||||||
for (int i = 0; i < instances_per_definition; i++)
|
|
||||||
definitions[definition].instances[i] += instance_add;
|
|
||||||
};
|
|
||||||
// Generate a default type if we can't generate something else.
|
|
||||||
auto Dummy = [&]() { AddToSchemaAndInstances("byte", "1"); };
|
|
||||||
|
|
||||||
std::string definition_name = "D" + flatbuffers::NumToString(definition);
|
std::string definition_name = "D" + flatbuffers::NumToString(definition);
|
||||||
|
|
||||||
bool is_struct = definition < num_struct_definitions;
|
bool is_struct = definition < num_struct_definitions;
|
||||||
|
|||||||
Reference in New Issue
Block a user