Sync from upstream

This commit is contained in:
吴凡
2016-07-01 11:03:25 +08:00
296 changed files with 16524 additions and 8059 deletions

View File

@@ -0,0 +1,121 @@
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FLATBUFFERS_CODE_GENERATORS_H_
#define FLATBUFFERS_CODE_GENERATORS_H_
namespace flatbuffers {
class BaseGenerator {
public:
virtual bool generate() = 0;
static const std::string NamespaceDir(const Parser &parser,
const std::string &path,
const Namespace &ns) {
EnsureDirExists(path.c_str());
if (parser.opts.one_file) return path;
std::string namespace_dir = path; // Either empty or ends in separator.
auto &namespaces = ns.components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
namespace_dir += *it + kPathSeparator;
EnsureDirExists(namespace_dir.c_str());
}
return namespace_dir;
}
protected:
BaseGenerator(const Parser &parser, const std::string &path,
const std::string &file_name,
const std::string qualifying_start,
const std::string qualifying_separator)
: parser_(parser),
path_(path),
file_name_(file_name),
qualifying_start_(qualifying_start),
qualifying_separator_(qualifying_separator){};
virtual ~BaseGenerator(){};
// No copy/assign.
BaseGenerator &operator=(const BaseGenerator &);
BaseGenerator(const BaseGenerator &);
const std::string NamespaceDir(const Namespace &ns) {
return BaseGenerator::NamespaceDir(parser_, path_, ns);
}
const char *FlatBuffersGeneratedWarning() {
return "automatically generated by the FlatBuffers compiler,"
" do not modify\n\n";
}
bool IsEverythingGenerated() {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
if (!(*it)->generated) return false;
}
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
if (!(*it)->generated) return false;
}
return true;
}
std::string FullNamespace(const char *separator, const Namespace &ns) {
std::string namespace_name;
auto &namespaces = ns.components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
if (namespace_name.length()) namespace_name += separator;
namespace_name += *it;
}
return namespace_name;
}
const std::string LastNamespacePart(const Namespace &ns) {
auto &namespaces = ns.components;
if (namespaces.size()) return *(namespaces.end() - 1); else return std::string("");
}
// tracks the current namespace for early exit in WrapInNameSpace
// c++, java and csharp returns a different namespace from
// the following default (no early exit, always fully qualify),
// which works for js and php
virtual const Namespace *CurrentNameSpace() { return nullptr; }
// Ensure that a type is prefixed with its namespace whenever it is used
// outside of its namespace.
std::string WrapInNameSpace(const Namespace *ns, const std::string &name) {
if (CurrentNameSpace() == ns) return name;
std::string qualified_name = qualifying_start_;
for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
qualified_name += *it + qualifying_separator_;
return qualified_name + name;
}
std::string WrapInNameSpace(const Definition &def) {
return WrapInNameSpace(def.defined_namespace, def.name);
}
const Parser &parser_;
const std::string &path_;
const std::string &file_name_;
const std::string qualifying_start_;
const std::string qualifying_separator_;
};
} // namespace flatbuffers
#endif // FLATBUFFERS_CODE_GENERATORS_H_

View File

@@ -26,18 +26,40 @@
#include <string>
#include <type_traits>
#include <vector>
#include <set>
#include <algorithm>
#include <functional>
#include <memory>
/// @cond FLATBUFFERS_INTERNAL
#if __cplusplus <= 199711L && \
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
(!defined(__GNUC__) || \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40603))
#error A C++11 compatible compiler is required for FlatBuffers.
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
#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__
#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 common platforms).
#if !defined(FLATBUFFERS_LITTLEENDIAN)
@@ -71,8 +93,19 @@
#define FLATBUFFERS_FINAL_CLASS
#endif
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
#define FLATBUFFERS_CONSTEXPR constexpr
#else
#define FLATBUFFERS_CONSTEXPR
#endif
/// @endcond
/// @file
namespace flatbuffers {
/// @cond FLATBUFFERS_INTERNAL
// Our default offset / size type, 32bit on purpose on 64bit systems.
// Also, using a consistent offset type maintains compatibility of serialized
// offset values between 32bit and 64bit systems.
@@ -87,6 +120,9 @@ typedef uint16_t voffset_t;
typedef uintmax_t largest_scalar_t;
// In 32bits, this evaluates to 2GB - 1
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
// Pointer to relinquished memory.
typedef std::unique_ptr<uint8_t, std::function<void(uint8_t * /* unused */)>>
unique_ptr_t;
@@ -154,7 +190,11 @@ template<typename T> size_t AlignOf() {
#ifdef _MSC_VER
return __alignof(T);
#else
return alignof(T);
#ifndef alignof
return __alignof__(T);
#else
return alignof(T);
#endif
#endif
}
@@ -168,6 +208,7 @@ template<typename T> size_t AlignOf() {
// (avoiding the need for a trailing return decltype)
template<typename T> struct IndirectHelper {
typedef T return_type;
typedef T mutable_return_type;
static const size_t element_stride = sizeof(T);
static return_type Read(const uint8_t *p, uoffset_t i) {
return EndianScalar((reinterpret_cast<const T *>(p))[i]);
@@ -175,6 +216,7 @@ template<typename T> struct IndirectHelper {
};
template<typename T> struct IndirectHelper<Offset<T>> {
typedef const T *return_type;
typedef T *mutable_return_type;
static const size_t element_stride = sizeof(uoffset_t);
static return_type Read(const uint8_t *p, uoffset_t i) {
p += i * sizeof(uoffset_t);
@@ -183,6 +225,7 @@ template<typename T> struct IndirectHelper<Offset<T>> {
};
template<typename T> struct IndirectHelper<const T *> {
typedef const T *return_type;
typedef T *mutable_return_type;
static const size_t element_stride = sizeof(T);
static return_type Read(const uint8_t *p, uoffset_t i) {
return reinterpret_cast<const T *>(p + i * sizeof(T));
@@ -267,6 +310,7 @@ public:
uoffset_t Length() const { return size(); }
typedef typename IndirectHelper<T>::return_type return_type;
typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
return_type Get(uoffset_t i) const {
assert(i < size());
@@ -294,7 +338,7 @@ public:
// Change elements if you have a non-const pointer to this object.
// Scalars only. See reflection.h, and the documentation.
void Mutate(uoffset_t i, T val) {
void Mutate(uoffset_t i, const T& val) {
assert(i < size());
WriteScalar(data() + i, val);
}
@@ -308,6 +352,12 @@ public:
WriteScalar(data() + i, val - (Data() + i * sizeof(uoffset_t)));
}
// Get a mutable pointer to tables/strings inside this vector.
mutable_return_type GetMutableObject(uoffset_t i) const {
assert(i < size());
return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
}
// The raw data in little endian format. Use with care.
const uint8_t *Data() const {
return reinterpret_cast<const uint8_t *>(&length_ + 1);
@@ -458,7 +508,7 @@ class vector_downward {
cur_ -= len;
// Beyond this, signed offsets may not have enough range:
// (FlatBuffers > 2GB not supported).
assert(size() < (1UL << (sizeof(soffset_t) * 8 - 1)) - 1);
assert(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
return cur_;
}
@@ -472,7 +522,7 @@ class vector_downward {
return cur_;
}
uint8_t *data_at(size_t offset) { return buf_ + reserved_ - offset; }
uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
// push() & fill() are most frequently called with small byte counts (<= 4),
// which is why we're using loops rather than calling memcpy/memset.
@@ -503,7 +553,7 @@ class vector_downward {
inline voffset_t FieldIndexToOffset(voffset_t field_id) {
// Should correspond to what EndTable() below builds up.
const int fixed_fields = 2; // Vtable size and Object Size.
return (field_id + fixed_fields) * sizeof(voffset_t);
return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
}
// Computes how many bytes you'd have to pad to be able to write an
@@ -512,26 +562,45 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) {
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
return ((~buf_size) + 1) & (scalar_size - 1);
}
/// @endcond
// Helper class to hold data needed in creation of a flat buffer.
// To serialize data, you typically call one of the Create*() functions in
// the generated code, which in turn call a sequence of StartTable/PushElement/
// AddElement/EndTable, or the builtin CreateString/CreateVector functions.
// Do this is depth-first order to build up a tree to the root.
// Finish() wraps up the buffer ready for transport.
class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
/// @addtogroup flatbuffers_cpp_api
/// @{
/// @class FlatBufferBuilder
/// @brief Helper class to hold data needed in creation of a FlatBuffer.
/// To serialize data, you typically call one of the `Create*()` functions in
/// the generated code, which in turn call a sequence of `StartTable`/
/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
/// `CreateVector` functions. Do this is depth-first order to build up a tree to
/// the root. `Finish()` wraps up the buffer ready for transport.
class FlatBufferBuilder
/// @cond FLATBUFFERS_INTERNAL
FLATBUFFERS_FINAL_CLASS
/// @endcond
{
public:
/// @brief Default constructor for FlatBufferBuilder.
/// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
/// to`1024`.
/// @param[in] allocator A pointer to the `simple_allocator` that should be
/// used. Defaults to `nullptr`, which means the `default_allocator` will be
/// be used.
explicit FlatBufferBuilder(uoffset_t initial_size = 1024,
const simple_allocator *allocator = nullptr)
: buf_(initial_size, allocator ? *allocator : default_allocator),
nested(false), finished(false), minalign_(1), force_defaults_(false) {
nested(false), finished(false), minalign_(1), force_defaults_(false),
string_pool(nullptr) {
offsetbuf_.reserve(16); // Avoid first few reallocs.
vtables_.reserve(16);
EndianCheck();
}
// Reset all the state in this FlatBufferBuilder so it can be reused
// to construct another buffer.
~FlatBufferBuilder() {
if (string_pool) delete string_pool;
}
/// @brief Reset all the state in this FlatBufferBuilder so it can be reused
/// to construct another buffer.
void Clear() {
buf_.clear();
offsetbuf_.clear();
@@ -539,31 +608,37 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
finished = false;
vtables_.clear();
minalign_ = 1;
if (string_pool) string_pool->clear();
}
// The current size of the serialized buffer, counting from the end.
/// @brief The current size of the serialized buffer, counting from the end.
/// @return Returns an `uoffset_t` with the current size of the buffer.
uoffset_t GetSize() const { return buf_.size(); }
// Get the serialized buffer (after you call Finish()).
/// @brief Get the serialized buffer (after you call `Finish()`).
/// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
/// buffer.
uint8_t *GetBufferPointer() const {
Finished();
return buf_.data();
}
// Get a pointer to an unfinished buffer.
/// @brief Get a pointer to an unfinished buffer.
/// @return Returns a `uint8_t` pointer to the unfinished buffer.
uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
// Get the released pointer to the serialized buffer.
// Don't attempt to use this FlatBufferBuilder afterwards!
// The unique_ptr returned has a special allocator that knows how to
// deallocate this pointer (since it points to the middle of an allocation).
// Thus, do not mix this pointer with other unique_ptr's, or call release() /
// reset() on it.
/// @brief Get the released pointer to the serialized buffer.
/// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
/// @return The `unique_ptr` returned has a special allocator that knows how
/// to deallocate this pointer (since it points to the middle of an
/// allocation). Thus, do not mix this pointer with other `unique_ptr`'s, or
/// call `release()`/`reset()` on it.
unique_ptr_t ReleaseBufferPointer() {
Finished();
return buf_.release();
}
/// @cond FLATBUFFERS_INTERNAL
void Finished() const {
// If you get this assert, you're attempting to get access a buffer
// which hasn't been finished yet. Be sure to call
@@ -572,9 +647,14 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
// GetCurrentBufferPointer instead.
assert(finished);
}
/// @endcond
/// @brief In order to save space, fields that are set to their default value
/// don't get serialized into the buffer.
/// @param[in] bool fd When set to `true`, always serializes default values.
void ForceDefaults(bool fd) { force_defaults_ = fd; }
/// @cond FLATBUFFERS_INTERNAL
void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
void Align(size_t elem_size) {
@@ -654,7 +734,7 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
Align(sizeof(uoffset_t));
// Offset must refer to something already in buffer.
assert(off && off <= GetSize());
return GetSize() - off + sizeof(uoffset_t);
return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
}
void NotNested() {
@@ -763,8 +843,12 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
AssertScalarT<T>();
PreAlign(len, sizeof(T));
}
/// @endcond
// Functions to store strings, which are allowed to contain any binary data.
/// @brief Store a string in the buffer, which can contain any binary data.
/// @param[in] str A const char pointer to the data to be stored as a string.
/// @param[in] len The number of bytes that should be stored from `str`.
/// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateString(const char *str, size_t len) {
NotNested();
PreAlign<uoffset_t>(len + 1); // Always 0-terminated.
@@ -774,18 +858,80 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
return Offset<String>(GetSize());
}
/// @brief Store a string in the buffer, which is null-terminated.
/// @param[in] str A const char pointer to a C-string to add to the buffer.
/// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateString(const char *str) {
return CreateString(str, strlen(str));
}
/// @brief Store a string in the buffer, which can contain any binary data.
/// @param[in] str A const reference to a std::string to store in the buffer.
/// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateString(const std::string &str) {
return CreateString(str.c_str(), str.length());
}
/// @brief Store a string in the buffer, which can contain any binary data.
/// @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
Offset<String> CreateString(const String *str) {
return CreateString(str->c_str(), str->Length());
}
/// @brief Store a string in the buffer, which can contain any binary data.
/// If a string with this exact contents has already been serialized before,
/// instead simply returns the offset of the existing string.
/// @param[in] str A const char pointer to the data to be stored as a string.
/// @param[in] len The number of bytes that should be stored from `str`.
/// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateSharedString(const char *str, size_t len) {
if (!string_pool)
string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
auto size_before_string = buf_.size();
// Must first serialize the string, since the set is all offsets into
// buffer.
auto off = CreateString(str, len);
auto it = string_pool->find(off);
// If it exists we reuse existing serialized data!
if (it != string_pool->end()) {
// We can remove the string we serialized.
buf_.pop(buf_.size() - size_before_string);
return *it;
}
// Record this string for future use.
string_pool->insert(off);
return off;
}
/// @brief Store a string in the buffer, which null-terminated.
/// If a string with this exact contents has already been serialized before,
/// instead simply returns the offset of the existing string.
/// @param[in] str A const char pointer to a C-string to add to the buffer.
/// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateSharedString(const char *str) {
return CreateSharedString(str, strlen(str));
}
/// @brief Store a string in the buffer, which can contain any binary data.
/// If a string with this exact contents has already been serialized before,
/// instead simply returns the offset of the existing string.
/// @param[in] str A const reference to a std::string to store in the buffer.
/// @return Returns the offset in the buffer where the string starts.
Offset<String> CreateSharedString(const std::string &str) {
return CreateSharedString(str.c_str(), str.length());
}
/// @brief Store a string in the buffer, which can contain any binary data.
/// If a string with this exact contents has already been serialized before,
/// instead simply returns the offset of the existing string.
/// @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
Offset<String> CreateSharedString(const String *str) {
return CreateSharedString(str->c_str(), str->Length());
}
/// @cond FLATBUFFERS_INTERNAL
uoffset_t EndVector(size_t len) {
assert(nested); // Hit if no corresponding StartVector.
nested = false;
@@ -811,7 +957,15 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
uint8_t *ReserveElements(size_t len, size_t elemsize) {
return buf_.make_space(len * elemsize);
}
/// @endcond
/// @brief Serialize an array into a FlatBuffer `vector`.
/// @tparam T The data type of the array elements.
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
StartVector(len, sizeof(T));
for (auto i = len; i > 0; ) {
@@ -820,60 +974,148 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
return Offset<Vector<T>>(EndVector(len));
}
/// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
/// @tparam T The data type of the `std::vector` elements.
/// @param v A const reference to the `std::vector` to serialize into the
/// buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
return CreateVector(v.data(), v.size());
}
/// @brief Serialize values returned by a function into a FlatBuffer `vector`.
/// This is a convenience function that takes care of iteration for you.
/// @tparam T The data type of the `std::vector` elements.
/// @param f A function that takes the current iteration 0..vector_size-1 and
/// returns any type that you can construct a FlatBuffers vector out of.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
const std::function<T (size_t i)> &f) {
std::vector<T> elems(vector_size);
for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
return CreateVector(elems.data(), elems.size());
}
/// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
/// This is a convenience function for a common case.
/// @param v A const reference to the `std::vector` to serialize into the
/// buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
Offset<Vector<Offset<String>>> CreateVectorOfStrings(
const std::vector<std::string> &v) {
std::vector<Offset<String>> offsets(v.size());
for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
return CreateVector(offsets.data(), offsets.size());
}
/// @brief Serialize an array of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @param[in] v A pointer to the array of type `T` to serialize into the
/// buffer as a `vector`.
/// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
const T *v, size_t len) {
const T *v, size_t len) {
StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
return Offset<Vector<const T *>>(EndVector(len));
}
/// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the `std::vector` struct elements.
/// @param[in]] v A const reference to the `std::vector` of structs to
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
const std::vector<T> &v) {
const std::vector<T> &v) {
return CreateVectorOfStructs(v.data(), v.size());
}
/// @cond FLATBUFFERS_INTERNAL
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_;
private:
TableKeyComparator& operator= (const TableKeyComparator&);
};
/// @endcond
/// @brief Serialize an array of `table` offsets as a `vector` in the buffer
/// in sorted order.
/// @tparam T The data type that the offset refers to.
/// @param[in] v An array of type `Offset<T>` that contains the `table`
/// offsets to store in the buffer in sorted order.
/// @param[in] len The number of elements to store in the `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
Offset<T> *v, size_t len) {
std::sort(v, v + len,
[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);
}
);
Offset<T> *v, size_t len) {
std::sort(v, v + len, TableKeyComparator<T>(buf_));
return CreateVector(v, len);
}
/// @brief Serialize an array of `table` offsets as a `vector` in the buffer
/// in sorted order.
/// @tparam T The data type that the offset refers to.
/// @param[in] v An array of type `Offset<T>` that contains the `table`
/// offsets to store in the buffer in sorted order.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
std::vector<Offset<T>> *v) {
std::vector<Offset<T>> *v) {
return CreateVectorOfSortedTables(v->data(), v->size());
}
// Specialized version for non-copying use cases. Write the data any time
// later to the returned buffer pointer `buf`.
/// @brief Specialized version of `CreateVector` for non-copying use cases.
/// Write the data any time later to the returned buffer pointer `buf`.
/// @param[in] len The number of elements to store in the `vector`.
/// @param[in] elemsize The size of each element in the `vector`.
/// @param[out] buf A pointer to a `uint8_t` pointer that can be
/// written to at a later time to serialize the data into a `vector`
/// in the buffer.
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
uint8_t **buf) {
NotNested();
StartVector(len, elemsize);
*buf = buf_.make_space(len * elemsize);
return EndVector(len);
buf_.make_space(len * elemsize);
auto vec_start = GetSize();
auto vec_end = EndVector(len);
*buf = buf_.data_at(vec_start);
return vec_end;
}
/// @brief Specialized version of `CreateVector` for non-copying use cases.
/// Write the data any time later to the returned buffer pointer `buf`.
/// @tparam T The data type of the data that will be stored in the buffer
/// as a `vector`.
/// @param[in] len The number of elements to store in the `vector`.
/// @param[out] buf A pointer to a pointer of type `T` that can be
/// written to at a later time to serialize the data into a `vector`
/// in the buffer.
template<typename T> Offset<Vector<T>> CreateUninitializedVector(
size_t len, T **buf) {
size_t len, T **buf) {
return CreateUninitializedVector(len, sizeof(T),
reinterpret_cast<uint8_t **>(buf));
}
/// @brief The length of a FlatBuffer file header.
static const size_t kFileIdentifierLength = 4;
// Finish serializing a buffer by writing the root offset.
// If a file_identifier is given, the buffer will be prefix with a standard
// FlatBuffers file header.
/// @brief Finish serializing a buffer by writing the root offset.
/// @param[in] file_identifier If a `file_identifier` is given, the buffer
/// will be prefixed with a standard FlatBuffers file header.
template<typename T> void Finish(Offset<T> root,
const char *file_identifier = nullptr) {
NotNested();
@@ -917,8 +1159,25 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS {
size_t minalign_;
bool force_defaults_; // Serialize values equal to their defaults anyway.
};
struct StringOffsetCompare {
StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
bool operator() (const Offset<String> &a, const Offset<String> &b) const {
auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
return strncmp(stra->c_str(), strb->c_str(),
std::min(stra->size(), strb->size()) + 1) < 0;
}
const vector_downward *buf_;
};
// For use with CreateSharedString. Instantiated on first use only.
typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
StringOffsetMap *string_pool;
};
/// @}
/// @cond FLATBUFFERS_INTERNAL
// Helpers to get a typed pointer to the root object contained in the buffer.
template<typename T> T *GetMutableRoot(void *buf) {
EndianCheck();
@@ -930,6 +1189,20 @@ template<typename T> const T *GetRoot(const void *buf) {
return GetMutableRoot<T>(const_cast<void *>(buf));
}
/// Helpers to get a typed pointer to objects that are currently beeing built.
/// @warning Creating new objects will lead to reallocations and invalidates
/// the pointer!
template<typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb,
Offset<T> offset) {
return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() +
fbb.GetSize() - offset.o);
}
template<typename T> const T *GetTemporaryPointer(FlatBufferBuilder &fbb,
Offset<T> offset) {
return GetMutableTemporaryPointer<T>(fbb, offset);
}
// Helper to see if the identifier in a buffer has the expected value.
inline bool BufferHasIdentifier(const void *buf, const char *identifier) {
return strncmp(reinterpret_cast<const char *>(buf) + sizeof(uoffset_t),
@@ -955,7 +1228,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// Verify any range within the buffer.
bool Verify(const void *elem, size_t elem_len) const {
return Check(elem_len <= (size_t) (end_ - buf_) && elem >= buf_ && elem <= end_ - elem_len);
return Check(elem_len <= (size_t) (end_ - buf_) &&
elem >= buf_ &&
elem <= end_ - elem_len);
}
// Verify a range indicated by sizeof(T).
@@ -998,6 +1273,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// Check the whole array. If this is a string, the byte past the array
// must be 0.
auto size = ReadScalar<uoffset_t>(vec);
auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
if (!Check(size < max_elems))
return false; // Protect against byte_size overflowing.
auto byte_size = sizeof(size) + elem_size * size;
*end = vec + byte_size;
return Verify(vec, byte_size);
@@ -1056,6 +1334,29 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
size_t max_tables_;
};
// Convenient way to bundle a buffer and its length, to pass it around
// typed by its root.
// A BufferRef does not own its buffer.
struct BufferRefBase {}; // for std::is_base_of
template<typename T> struct BufferRef : BufferRefBase {
BufferRef() : buf(nullptr), len(0), must_free(false) {}
BufferRef(uint8_t *_buf, uoffset_t _len)
: buf(_buf), len(_len), must_free(false) {}
~BufferRef() { if (must_free) free(buf); }
const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
bool Verify() {
Verifier verifier(buf, len);
return verifier.VerifyBuffer<T>();
}
uint8_t *buf;
uoffset_t len;
bool must_free;
};
// "structs" are flat structures that do not have an offset table, thus
// always have all members present and do not support forwards/backwards
// compatible extensions.
@@ -1157,6 +1458,7 @@ class Table {
// Check the vtable size field, then check vtable fits in its entirety.
return verifier.VerifyComplexity() &&
verifier.Verify<voffset_t>(vtable) &&
(ReadScalar<voffset_t>(vtable) & (sizeof(voffset_t) - 1)) == 0 &&
verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
}
@@ -1187,6 +1489,18 @@ class Table {
uint8_t data_[1];
};
// Helper function to test if a field is present, using any of the field
// enums in the generated code.
// `table` must be a generated table type. Since this is a template parameter,
// this is not typechecked to be a subclass of Table, so beware!
// Note: this function will return false for fields equal to the default
// value, since they're not stored in the buffer (unless force_defaults was
// used).
template<typename T> bool IsFieldPresent(const T *table, voffset_t field) {
// Cast, since Table is a private baseclass of any table types.
return reinterpret_cast<const Table *>(table)->CheckField(field);
}
// Utility function for reverse lookups on the EnumNames*() functions
// (in the generated C++ code)
// names must be NULL terminated.
@@ -1246,6 +1560,36 @@ volatile __attribute__((weak)) const char *flatbuffer_version_string =
#endif // !defined(_WIN32) && !defined(__CYGWIN__)
#define DEFINE_BITMASK_OPERATORS(E, T)\
inline E operator | (E lhs, E rhs){\
return E(T(lhs) | T(rhs));\
}\
inline E operator & (E lhs, E rhs){\
return E(T(lhs) & T(rhs));\
}\
inline E operator ^ (E lhs, E rhs){\
return E(T(lhs) ^ T(rhs));\
}\
inline E operator ~ (E lhs){\
return E(~T(lhs));\
}\
inline E operator |= (E &lhs, E rhs){\
lhs = lhs | rhs;\
return lhs;\
}\
inline E operator &= (E &lhs, E rhs){\
lhs = lhs & rhs;\
return lhs;\
}\
inline E operator ^= (E &lhs, E rhs){\
lhs = lhs ^ rhs;\
return lhs;\
}\
inline bool operator !(E rhs) \
{\
return !bool(T(rhs)); \
}
/// @endcond
} // namespace flatbuffers
#endif // FLATBUFFERS_H_

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FLATBUFFERS_GRPC_H_
#define FLATBUFFERS_GRPC_H_
// Helper functionality to glue FlatBuffers and GRPC.
#include "grpc++/support/byte_buffer.h"
#include "grpc/byte_buffer_reader.h"
namespace grpc {
template <class T>
class SerializationTraits<T, typename std::enable_if<std::is_base_of<
flatbuffers::BufferRefBase, T>::value>::type> {
public:
// The type we're passing here is a BufferRef, which is already serialized
// FlatBuffer data, which then gets passed to GRPC.
static grpc::Status Serialize(const T& msg,
grpc_byte_buffer **buffer,
bool *own_buffer) {
// TODO(wvo): make this work without copying.
auto slice = gpr_slice_from_copied_buffer(
reinterpret_cast<const char *>(msg.buf), msg.len);
*buffer = grpc_raw_byte_buffer_create(&slice, 1);
*own_buffer = true;
return grpc::Status();
}
// There is no de-serialization step in FlatBuffers, so we just receive
// the data from GRPC.
static grpc::Status Deserialize(grpc_byte_buffer *buffer,
T *msg,
int max_message_size) {
// TODO(wvo): make this more efficient / zero copy when possible.
auto len = grpc_byte_buffer_length(buffer);
msg->buf = reinterpret_cast<uint8_t *>(malloc(len));
msg->len = static_cast<flatbuffers::uoffset_t>(len);
msg->must_free = true;
uint8_t *current = msg->buf;
grpc_byte_buffer_reader reader;
grpc_byte_buffer_reader_init(&reader, buffer);
gpr_slice slice;
while (grpc_byte_buffer_reader_next(&reader, &slice)) {
memcpy(current, GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice));
current += GPR_SLICE_LENGTH(slice);
gpr_slice_unref(slice);
}
GPR_ASSERT(current == msg->buf + msg->len);
grpc_byte_buffer_reader_destroy(&reader);
grpc_byte_buffer_destroy(buffer);
return grpc::Status();
}
};
} // namespace grpc;
#endif // FLATBUFFERS_GRPC_H_

View File

@@ -20,6 +20,8 @@
#include <cstdint>
#include <cstring>
#include "flatbuffers/flatbuffers.h"
namespace flatbuffers {
template <typename T>
@@ -36,8 +38,8 @@ struct FnvTraits<uint32_t> {
template <>
struct FnvTraits<uint64_t> {
static const uint64_t kFnvPrime = 0x00000100000001b3;
static const uint64_t kOffsetBasis = 0xcbf29ce484222645;
static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
};
template <typename T>

View File

@@ -18,7 +18,6 @@
#define FLATBUFFERS_IDL_H_
#include <map>
#include <set>
#include <stack>
#include <memory>
#include <functional>
@@ -113,6 +112,7 @@ inline size_t SizeOf(BaseType t) {
struct StructDef;
struct EnumDef;
class Parser;
// Represents any type in the IDL, which is a combination of the BaseType
// and additional information for vectors/structs_.
@@ -184,10 +184,8 @@ template<typename T> class SymbolTable {
return it == dict.end() ? nullptr : it->second;
}
private:
std::map<std::string, T *> dict; // quick lookup
public:
std::map<std::string, T *> dict; // quick lookup
std::vector<T *> vec; // Used to iterate in order of insertion
};
@@ -208,6 +206,11 @@ struct Definition {
Definition() : generated(false), defined_namespace(nullptr),
serialized_location(0), index(-1) {}
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
reflection::KeyValue>>>
SerializeAttributes(FlatBufferBuilder *builder,
const Parser &parser) const;
std::string name;
std::string file;
std::vector<std::string> doc_comment;
@@ -223,8 +226,8 @@ struct Definition {
struct FieldDef : public Definition {
FieldDef() : deprecated(false), required(false), key(false), padding(0) {}
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id)
const;
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
const Parser &parser) const;
Value value;
bool deprecated; // Field is allowed to be present in old data, but can't be
@@ -250,7 +253,8 @@ struct StructDef : public Definition {
if (fields.vec.size()) fields.vec.back()->padding = padding;
}
Offset<reflection::Object> Serialize(FlatBufferBuilder *builder) const;
Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
const Parser &parser) const;
SymbolTable<FieldDef> fields;
bool fixed; // If it's struct, not a table.
@@ -299,34 +303,137 @@ struct EnumDef : public Definition {
return nullptr;
}
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder) const;
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
const Parser &parser) const;
SymbolTable<EnumVal> vals;
bool is_union;
Type underlying_type;
};
class Parser {
struct RPCCall {
std::string name;
SymbolTable<Value> attributes;
StructDef *request, *response;
};
struct ServiceDef : public Definition {
SymbolTable<RPCCall> calls;
};
// Container of options that may apply to any of the source/text generators.
struct IDLOptions {
bool strict_json;
bool skip_js_exports;
bool output_default_scalars_in_json;
int indent_step;
bool output_enum_identifiers;
bool prefixed_enums;
bool scoped_enums;
bool include_dependence_headers;
bool mutable_buffer;
bool one_file;
bool proto_mode;
bool generate_all;
bool skip_unexpected_fields_in_json;
bool generate_name_strings;
// Possible options for the more general generator below.
enum Language { kJava, kCSharp, kGo, kMAX };
Language lang;
IDLOptions()
: strict_json(false),
skip_js_exports(false),
output_default_scalars_in_json(false),
indent_step(2),
output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false),
include_dependence_headers(true),
mutable_buffer(false),
one_file(false),
proto_mode(false),
generate_all(false),
skip_unexpected_fields_in_json(false),
generate_name_strings(false),
lang(IDLOptions::kJava) {}
};
// This encapsulates where the parser is in the current source file.
struct ParserState {
ParserState() : cursor_(nullptr), line_(1), token_(-1) {}
protected:
const char *cursor_;
int line_; // the current line being parsed
int token_;
std::string attribute_;
std::vector<std::string> doc_comment_;
};
// A way to make error propagation less error prone by requiring values to be
// checked.
// Once you create a value of this type you must either:
// - Call Check() on it.
// - Copy or assign it to another value.
// Failure to do so leads to an assert.
// This guarantees that this as return value cannot be ignored.
class CheckedError {
public:
Parser(bool strict_json = false, bool proto_mode = false)
explicit CheckedError(bool error)
: is_error_(error), has_been_checked_(false) {}
CheckedError &operator=(const CheckedError &other) {
is_error_ = other.is_error_;
has_been_checked_ = false;
other.has_been_checked_ = true;
return *this;
}
CheckedError(const CheckedError &other) {
*this = other; // Use assignment operator.
}
~CheckedError() { assert(has_been_checked_); }
bool Check() { has_been_checked_ = true; return is_error_; }
private:
bool is_error_;
mutable bool has_been_checked_;
};
// Additionally, in GCC we can get these errors statically, for additional
// assurance:
#ifdef __GNUC__
#define FLATBUFFERS_CHECKED_ERROR CheckedError \
__attribute__((warn_unused_result))
#else
#define FLATBUFFERS_CHECKED_ERROR CheckedError
#endif
class Parser : public ParserState {
public:
explicit Parser(const IDLOptions &options = IDLOptions())
: root_struct_def_(nullptr),
opts(options),
source_(nullptr),
cursor_(nullptr),
line_(1),
proto_mode_(proto_mode),
strict_json_(strict_json),
anonymous_counter(0) {
// Just in case none are declared:
namespaces_.push_back(new Namespace());
known_attributes_.insert("deprecated");
known_attributes_.insert("required");
known_attributes_.insert("key");
known_attributes_.insert("hash");
known_attributes_.insert("id");
known_attributes_.insert("force_align");
known_attributes_.insert("bit_flags");
known_attributes_.insert("original_order");
known_attributes_.insert("nested_flatbuffer");
known_attributes_["deprecated"] = true;
known_attributes_["required"] = true;
known_attributes_["key"] = true;
known_attributes_["hash"] = true;
known_attributes_["id"] = true;
known_attributes_["force_align"] = true;
known_attributes_["bit_flags"] = true;
known_attributes_["original_order"] = true;
known_attributes_["nested_flatbuffer"] = true;
known_attributes_["csharp_partial"] = true;
known_attributes_["streaming"] = true;
known_attributes_["idempotent"] = true;
}
~Parser() {
@@ -362,48 +469,71 @@ class Parser {
// See reflection/reflection.fbs
void Serialize();
private:
int64_t ParseHexNum(int nibbles);
void Next();
bool IsNext(int t);
void Expect(int t);
FLATBUFFERS_CHECKED_ERROR CheckBitsFit(int64_t val, size_t bits);
private:
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, int64_t *val);
FLATBUFFERS_CHECKED_ERROR Next();
FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
bool Is(int t);
FLATBUFFERS_CHECKED_ERROR Expect(int t);
std::string TokenToStringId(int t);
EnumDef *LookupEnum(const std::string &id);
void ParseNamespacing(std::string *id, std::string *last);
void ParseTypeIdent(Type &type);
void ParseType(Type &type);
FieldDef &AddField(StructDef &struct_def,
const std::string &name,
const Type &type);
void ParseField(StructDef &struct_def);
void ParseAnyValue(Value &val, FieldDef *field, size_t parent_fieldn);
uoffset_t ParseTable(const StructDef &struct_def, std::string *value);
FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
std::string *last);
FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
const std::string &name, const Type &type,
FieldDef **dest);
FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn,
const StructDef *parent_struct_def);
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
std::string *value, uoffset_t *ovalue);
void SerializeStruct(const StructDef &struct_def, const Value &val);
void AddVector(bool sortbysize, int count);
uoffset_t ParseVector(const Type &type);
void ParseMetaData(Definition &def);
bool TryTypedValue(int dtoken, bool check, Value &e, BaseType req);
void ParseHash(Value &e, FieldDef* field);
void ParseSingleValue(Value &e);
int64_t ParseIntegerFromString(Type &type);
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);
FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
FLATBUFFERS_CHECKED_ERROR TryTypedValue(int dtoken, bool check, Value &e,
BaseType req, bool *destmatch);
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(Value &e);
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
StructDef *LookupCreateStruct(const std::string &name,
bool create_if_new = true,
bool definition = false);
EnumDef &ParseEnum(bool is_union);
void ParseNamespace();
StructDef &StartStruct(const std::string &name);
void ParseDecl();
void ParseProtoFields(StructDef *struct_def, bool isextend,
bool inside_oneof);
void ParseProtoOption();
void ParseProtoKey();
void ParseProtoDecl();
void ParseProtoCurliesOrIdent();
Type ParseTypeFromProtoType();
FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest);
FLATBUFFERS_CHECKED_ERROR ParseNamespace();
FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
StructDef **dest);
FLATBUFFERS_CHECKED_ERROR ParseDecl();
FLATBUFFERS_CHECKED_ERROR ParseService();
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
bool isextend, bool inside_oneof);
FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
FLATBUFFERS_CHECKED_ERROR SkipJsonObject();
FLATBUFFERS_CHECKED_ERROR SkipJsonArray();
FLATBUFFERS_CHECKED_ERROR SkipJsonString();
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
const char **include_paths,
const char *source_filename);
FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
StructDef *struct_def,
const char *suffix,
BaseType baseType);
public:
SymbolTable<StructDef> structs_;
SymbolTable<EnumDef> enums_;
SymbolTable<ServiceDef> services_;
std::vector<Namespace *> namespaces_;
std::string error_; // User readable error_ if Parse() == false
@@ -415,7 +545,12 @@ class Parser {
std::map<std::string, bool> included_files_;
std::map<std::string, std::set<std::string>> files_included_per_file_;
std::map<std::string, bool> known_attributes_;
IDLOptions opts;
private:
<<<<<<< HEAD
const char *source_, *cursor_;
int line_; // the current line being parsed
int token_;
@@ -424,11 +559,14 @@ class Parser {
bool strict_json_;
std::string attribute_;
std::vector<std::string> doc_comment_;
=======
const char *source_;
>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70
std::string file_being_parsed_;
std::vector<std::pair<Value, FieldDef *>> field_stack_;
std::set<std::string> known_attributes_;
int anonymous_counter;
};
@@ -443,35 +581,6 @@ extern void GenComment(const std::vector<std::string> &dc,
const CommentConfig *config,
const char *prefix = "");
// Container of options that may apply to any of the source/text generators.
struct GeneratorOptions {
bool strict_json;
bool skip_js_exports;
bool output_default_scalars_in_json;
int indent_step;
bool output_enum_identifiers;
bool prefixed_enums;
bool scoped_enums;
bool include_dependence_headers;
bool mutable_buffer;
bool one_file;
// Possible options for the more general generator below.
enum Language { kJava, kCSharp, kGo, kMAX };
Language lang;
GeneratorOptions() : strict_json(false),
skip_js_exports(false),
output_default_scalars_in_json(false),
indent_step(2),
output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false),
include_dependence_headers(true),
mutable_buffer(false),
one_file(false),
lang(GeneratorOptions::kJava) {}
};
// Generate text (JSON) from a given FlatBuffer, and a given Parser
// object that has been populated with the corresponding schema.
// If ident_step is 0, no indentation will be generated. Additionally,
@@ -480,126 +589,112 @@ struct GeneratorOptions {
// strict_json adds "quotes" around field names if true.
extern void GenerateText(const Parser &parser,
const void *flatbuffer,
const GeneratorOptions &opts,
std::string *text);
extern bool GenerateTextFile(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate binary files from a given FlatBuffer, and a given Parser
// object that has been populated with the corresponding schema.
// See idl_gen_general.cpp.
extern bool GenerateBinary(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate a C++ header from the definitions in the Parser object.
// See idl_gen_cpp.
extern std::string GenerateCPP(const Parser &parser,
const std::string &include_guard_ident,
const GeneratorOptions &opts);
const std::string &include_guard_ident);
extern bool GenerateCPP(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate JavaScript code from the definitions in the Parser object.
// See idl_gen_js.
extern std::string GenerateJS(const Parser &parser,
const GeneratorOptions &opts);
extern std::string GenerateJS(const Parser &parser);
extern bool GenerateJS(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate Go files from the definitions in the Parser object.
// See idl_gen_go.cpp.
extern bool GenerateGo(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate Java files from the definitions in the Parser object.
// See idl_gen_java.cpp.
extern bool GenerateJava(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate Php code from the definitions in the Parser object.
// See idl_gen_php.
extern bool GeneratePhp(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate Python files from the definitions in the Parser object.
// See idl_gen_python.cpp.
extern bool GeneratePython(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate C# files from the definitions in the Parser object.
// See idl_gen_csharp.cpp.
extern bool GenerateCSharp(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate Java/C#/.. files from the definitions in the Parser object.
// See idl_gen_general.cpp.
extern bool GenerateGeneral(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate a schema file from the internal representation, useful after
// parsing a .proto schema.
extern std::string GenerateFBS(const Parser &parser,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
extern bool GenerateFBS(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate a make rule for the generated JavaScript code.
// See idl_gen_js.cpp.
extern std::string JSMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate a make rule for the generated C++ header.
// See idl_gen_cpp.cpp.
extern std::string CPPMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate a make rule for the generated Java/C#/... files.
// See idl_gen_general.cpp.
extern std::string GeneralMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate a make rule for the generated text (JSON) files.
// See idl_gen_text.cpp.
extern std::string TextMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_names);
// Generate a make rule for the generated binary files.
// See idl_gen_general.cpp.
extern std::string BinaryMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name,
const GeneratorOptions &opts);
const std::string &file_name);
// Generate GRPC interfaces.
// See idl_gen_grpc.cpp.
bool GenerateGRPC(const Parser &parser,
const std::string &path,
const std::string &file_name);
} // namespace flatbuffers

View File

@@ -335,6 +335,8 @@ template<typename T, typename U> pointer_inside_vector<T, U> piv(T *ptr,
return pointer_inside_vector<T, U>(ptr, vec);
}
inline const char *UnionTypeFieldSuffix() { return "_type"; }
// Helper to figure out the actual table type a union refers to.
inline const reflection::Object &GetUnionType(
const reflection::Schema &schema, const reflection::Object &parent,
@@ -342,7 +344,7 @@ inline const reflection::Object &GetUnionType(
auto enumdef = schema.enums()->Get(unionfield.type()->index());
// TODO: this is clumsy and slow, but no other way to find it?
auto type_field = parent.fields()->LookupByKey(
(unionfield.name()->str() + "_type").c_str());
(unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
assert(type_field);
auto union_type = GetFieldI<uint8_t>(table, *type_field);
auto enumval = enumdef->values()->LookupByKey(union_type);
@@ -415,12 +417,14 @@ inline bool SetFieldT(Table *table, const reflection::Field &field,
// above resizing functionality has introduced garbage in a buffer you want
// to remove.
// Note: this does not deal with DAGs correctly. If the table passed forms a
// DAG, the copy will be a tree instead (with duplicates).
// DAG, the copy will be a tree instead (with duplicates). Strings can be
// shared however, by passing true for use_string_pooling.
Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const reflection::Schema &schema,
const reflection::Object &objectdef,
const Table &table);
const Table &table,
bool use_string_pooling = false);
} // namespace flatbuffers

View File

@@ -5,14 +5,20 @@
#include "flatbuffers/flatbuffers.h"
namespace reflection {
struct Type;
struct KeyValue;
struct EnumVal;
struct Enum;
struct Field;
struct Object;
struct Schema;
enum BaseType {
@@ -32,7 +38,9 @@ enum BaseType {
String = 13,
Vector = 14,
Obj = 15,
Union = 16
Union = 16,
MIN = None,
MAX = Union
};
inline const char **EnumNamesBaseType() {
@@ -40,17 +48,22 @@ inline const char **EnumNamesBaseType() {
return names;
}
inline const char *EnumNameBaseType(BaseType e) { return EnumNamesBaseType()[e]; }
inline const char *EnumNameBaseType(BaseType e) { return EnumNamesBaseType()[static_cast<int>(e)]; }
struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
BaseType base_type() const { return static_cast<BaseType>(GetField<int8_t>(4, 0)); }
BaseType element() const { return static_cast<BaseType>(GetField<int8_t>(6, 0)); }
int32_t index() const { return GetField<int32_t>(8, -1); }
enum {
VT_BASE_TYPE = 4,
VT_ELEMENT = 6,
VT_INDEX = 8
};
BaseType base_type() const { return static_cast<BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0)); }
BaseType element() const { return static_cast<BaseType>(GetField<int8_t>(VT_ELEMENT, 0)); }
int32_t index() const { return GetField<int32_t>(VT_INDEX, -1); }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<int8_t>(verifier, 4 /* base_type */) &&
VerifyField<int8_t>(verifier, 6 /* element */) &&
VerifyField<int32_t>(verifier, 8 /* index */) &&
VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
VerifyField<int8_t>(verifier, VT_ELEMENT) &&
VerifyField<int32_t>(verifier, VT_INDEX) &&
verifier.EndTable();
}
};
@@ -58,9 +71,9 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct TypeBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_base_type(BaseType base_type) { fbb_.AddElement<int8_t>(4, static_cast<int8_t>(base_type), 0); }
void add_element(BaseType element) { fbb_.AddElement<int8_t>(6, static_cast<int8_t>(element), 0); }
void add_index(int32_t index) { fbb_.AddElement<int32_t>(8, index, -1); }
void add_base_type(BaseType base_type) { fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0); }
void add_element(BaseType element) { fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0); }
void add_index(int32_t index) { fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1); }
TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
TypeBuilder &operator=(const TypeBuilder &);
flatbuffers::Offset<Type> Finish() {
@@ -80,18 +93,65 @@ inline flatbuffers::Offset<Type> CreateType(flatbuffers::FlatBufferBuilder &_fbb
return builder_.Finish();
}
struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(4); }
int64_t value() const { return GetField<int64_t>(6, 0); }
bool KeyCompareLessThan(const EnumVal *o) const { return value() < o->value(); }
int KeyCompareWithValue(int64_t val) const { return value() < val ? -1 : value() > val; }
const Object *object() const { return GetPointer<const Object *>(8); }
struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
VT_KEY = 4,
VT_VALUE = 6
};
const flatbuffers::String *key() const { return GetPointer<const flatbuffers::String *>(VT_KEY); }
bool KeyCompareLessThan(const KeyValue *o) const { return *key() < *o->key(); }
int KeyCompareWithValue(const char *val) const { return strcmp(key()->c_str(), val); }
const flatbuffers::String *value() const { return GetPointer<const flatbuffers::String *>(VT_VALUE); }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* name */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_KEY) &&
verifier.Verify(key()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) &&
verifier.Verify(value()) &&
verifier.EndTable();
}
};
struct KeyValueBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_key(flatbuffers::Offset<flatbuffers::String> key) { fbb_.AddOffset(KeyValue::VT_KEY, key); }
void add_value(flatbuffers::Offset<flatbuffers::String> value) { fbb_.AddOffset(KeyValue::VT_VALUE, value); }
KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
KeyValueBuilder &operator=(const KeyValueBuilder &);
flatbuffers::Offset<KeyValue> Finish() {
auto o = flatbuffers::Offset<KeyValue>(fbb_.EndTable(start_, 2));
fbb_.Required(o, KeyValue::VT_KEY); // key
return o;
}
};
inline flatbuffers::Offset<KeyValue> CreateKeyValue(flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> key = 0,
flatbuffers::Offset<flatbuffers::String> value = 0) {
KeyValueBuilder builder_(_fbb);
builder_.add_value(value);
builder_.add_key(key);
return builder_.Finish();
}
struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
VT_NAME = 4,
VT_VALUE = 6,
VT_OBJECT = 8
};
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
int64_t value() const { return GetField<int64_t>(VT_VALUE, 0); }
bool KeyCompareLessThan(const EnumVal *o) const { return value() < o->value(); }
int KeyCompareWithValue(int64_t val) const { return value() < val ? -1 : value() > val; }
const Object *object() const { return GetPointer<const Object *>(VT_OBJECT); }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyField<int64_t>(verifier, 6 /* value */) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 8 /* object */) &&
VerifyField<int64_t>(verifier, VT_VALUE) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_OBJECT) &&
verifier.VerifyTable(object()) &&
verifier.EndTable();
}
@@ -100,14 +160,14 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct EnumValBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(4, name); }
void add_value(int64_t value) { fbb_.AddElement<int64_t>(6, value, 0); }
void add_object(flatbuffers::Offset<Object> object) { fbb_.AddOffset(8, object); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(EnumVal::VT_NAME, name); }
void add_value(int64_t value) { fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0); }
void add_object(flatbuffers::Offset<Object> object) { fbb_.AddOffset(EnumVal::VT_OBJECT, object); }
EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
EnumValBuilder &operator=(const EnumValBuilder &);
flatbuffers::Offset<EnumVal> Finish() {
auto o = flatbuffers::Offset<EnumVal>(fbb_.EndTable(start_, 3));
fbb_.Required(o, 4); // name
fbb_.Required(o, EnumVal::VT_NAME); // name
return o;
}
};
@@ -124,22 +184,33 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(flatbuffers::FlatBufferBuilder
}
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(4); }
enum {
VT_NAME = 4,
VT_VALUES = 6,
VT_IS_UNION = 8,
VT_UNDERLYING_TYPE = 10,
VT_ATTRIBUTES = 12
};
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
bool KeyCompareLessThan(const Enum *o) const { return *name() < *o->name(); }
int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *values() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *>(6); }
uint8_t is_union() const { return GetField<uint8_t>(8, 0); }
const Type *underlying_type() const { return GetPointer<const Type *>(10); }
const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *values() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *>(VT_VALUES); }
bool is_union() const { return GetField<uint8_t>(VT_IS_UNION, 0) != 0; }
const Type *underlying_type() const { return GetPointer<const Type *>(VT_UNDERLYING_TYPE); }
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* name */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 6 /* values */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_VALUES) &&
verifier.Verify(values()) &&
verifier.VerifyVectorOfTables(values()) &&
VerifyField<uint8_t>(verifier, 8 /* is_union */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 10 /* underlying_type */) &&
VerifyField<uint8_t>(verifier, VT_IS_UNION) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_UNDERLYING_TYPE) &&
verifier.VerifyTable(underlying_type()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
verifier.Verify(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
verifier.EndTable();
}
};
@@ -147,17 +218,18 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct EnumBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(4, name); }
void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values) { fbb_.AddOffset(6, values); }
void add_is_union(uint8_t is_union) { fbb_.AddElement<uint8_t>(8, is_union, 0); }
void add_underlying_type(flatbuffers::Offset<Type> underlying_type) { fbb_.AddOffset(10, underlying_type); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Enum::VT_NAME, name); }
void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values) { fbb_.AddOffset(Enum::VT_VALUES, values); }
void add_is_union(bool is_union) { fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0); }
void add_underlying_type(flatbuffers::Offset<Type> underlying_type) { fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type); }
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes); }
EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
EnumBuilder &operator=(const EnumBuilder &);
flatbuffers::Offset<Enum> Finish() {
auto o = flatbuffers::Offset<Enum>(fbb_.EndTable(start_, 4));
fbb_.Required(o, 4); // name
fbb_.Required(o, 6); // values
fbb_.Required(o, 10); // underlying_type
auto o = flatbuffers::Offset<Enum>(fbb_.EndTable(start_, 5));
fbb_.Required(o, Enum::VT_NAME); // name
fbb_.Required(o, Enum::VT_VALUES); // values
fbb_.Required(o, Enum::VT_UNDERLYING_TYPE); // underlying_type
return o;
}
};
@@ -165,9 +237,11 @@ struct EnumBuilder {
inline flatbuffers::Offset<Enum> CreateEnum(flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values = 0,
uint8_t is_union = 0,
flatbuffers::Offset<Type> underlying_type = 0) {
bool is_union = false,
flatbuffers::Offset<Type> underlying_type = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
EnumBuilder builder_(_fbb);
builder_.add_attributes(attributes);
builder_.add_underlying_type(underlying_type);
builder_.add_values(values);
builder_.add_name(name);
@@ -176,30 +250,46 @@ inline flatbuffers::Offset<Enum> CreateEnum(flatbuffers::FlatBufferBuilder &_fbb
}
struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(4); }
enum {
VT_NAME = 4,
VT_TYPE = 6,
VT_ID = 8,
VT_OFFSET = 10,
VT_DEFAULT_INTEGER = 12,
VT_DEFAULT_REAL = 14,
VT_DEPRECATED = 16,
VT_REQUIRED = 18,
VT_KEY = 20,
VT_ATTRIBUTES = 22
};
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
bool KeyCompareLessThan(const Field *o) const { return *name() < *o->name(); }
int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
const Type *type() const { return GetPointer<const Type *>(6); }
uint16_t id() const { return GetField<uint16_t>(8, 0); }
uint16_t offset() const { return GetField<uint16_t>(10, 0); }
int64_t default_integer() const { return GetField<int64_t>(12, 0); }
double default_real() const { return GetField<double>(14, 0.0); }
uint8_t deprecated() const { return GetField<uint8_t>(16, 0); }
uint8_t required() const { return GetField<uint8_t>(18, 0); }
uint8_t key() const { return GetField<uint8_t>(20, 0); }
const Type *type() const { return GetPointer<const Type *>(VT_TYPE); }
uint16_t id() const { return GetField<uint16_t>(VT_ID, 0); }
uint16_t offset() const { return GetField<uint16_t>(VT_OFFSET, 0); }
int64_t default_integer() const { return GetField<int64_t>(VT_DEFAULT_INTEGER, 0); }
double default_real() const { return GetField<double>(VT_DEFAULT_REAL, 0.0); }
bool deprecated() const { return GetField<uint8_t>(VT_DEPRECATED, 0) != 0; }
bool required() const { return GetField<uint8_t>(VT_REQUIRED, 0) != 0; }
bool key() const { return GetField<uint8_t>(VT_KEY, 0) != 0; }
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* name */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 6 /* type */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_TYPE) &&
verifier.VerifyTable(type()) &&
VerifyField<uint16_t>(verifier, 8 /* id */) &&
VerifyField<uint16_t>(verifier, 10 /* offset */) &&
VerifyField<int64_t>(verifier, 12 /* default_integer */) &&
VerifyField<double>(verifier, 14 /* default_real */) &&
VerifyField<uint8_t>(verifier, 16 /* deprecated */) &&
VerifyField<uint8_t>(verifier, 18 /* required */) &&
VerifyField<uint8_t>(verifier, 20 /* key */) &&
VerifyField<uint16_t>(verifier, VT_ID) &&
VerifyField<uint16_t>(verifier, VT_OFFSET) &&
VerifyField<int64_t>(verifier, VT_DEFAULT_INTEGER) &&
VerifyField<double>(verifier, VT_DEFAULT_REAL) &&
VerifyField<uint8_t>(verifier, VT_DEPRECATED) &&
VerifyField<uint8_t>(verifier, VT_REQUIRED) &&
VerifyField<uint8_t>(verifier, VT_KEY) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
verifier.Verify(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
verifier.EndTable();
}
};
@@ -207,21 +297,22 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct FieldBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(4, name); }
void add_type(flatbuffers::Offset<Type> type) { fbb_.AddOffset(6, type); }
void add_id(uint16_t id) { fbb_.AddElement<uint16_t>(8, id, 0); }
void add_offset(uint16_t offset) { fbb_.AddElement<uint16_t>(10, offset, 0); }
void add_default_integer(int64_t default_integer) { fbb_.AddElement<int64_t>(12, default_integer, 0); }
void add_default_real(double default_real) { fbb_.AddElement<double>(14, default_real, 0.0); }
void add_deprecated(uint8_t deprecated) { fbb_.AddElement<uint8_t>(16, deprecated, 0); }
void add_required(uint8_t required) { fbb_.AddElement<uint8_t>(18, required, 0); }
void add_key(uint8_t key) { fbb_.AddElement<uint8_t>(20, key, 0); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Field::VT_NAME, name); }
void add_type(flatbuffers::Offset<Type> type) { fbb_.AddOffset(Field::VT_TYPE, type); }
void add_id(uint16_t id) { fbb_.AddElement<uint16_t>(Field::VT_ID, id, 0); }
void add_offset(uint16_t offset) { fbb_.AddElement<uint16_t>(Field::VT_OFFSET, offset, 0); }
void add_default_integer(int64_t default_integer) { fbb_.AddElement<int64_t>(Field::VT_DEFAULT_INTEGER, default_integer, 0); }
void add_default_real(double default_real) { fbb_.AddElement<double>(Field::VT_DEFAULT_REAL, default_real, 0.0); }
void add_deprecated(bool deprecated) { fbb_.AddElement<uint8_t>(Field::VT_DEPRECATED, static_cast<uint8_t>(deprecated), 0); }
void add_required(bool required) { fbb_.AddElement<uint8_t>(Field::VT_REQUIRED, static_cast<uint8_t>(required), 0); }
void add_key(bool key) { fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0); }
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes); }
FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
FieldBuilder &operator=(const FieldBuilder &);
flatbuffers::Offset<Field> Finish() {
auto o = flatbuffers::Offset<Field>(fbb_.EndTable(start_, 9));
fbb_.Required(o, 4); // name
fbb_.Required(o, 6); // type
auto o = flatbuffers::Offset<Field>(fbb_.EndTable(start_, 10));
fbb_.Required(o, Field::VT_NAME); // name
fbb_.Required(o, Field::VT_TYPE); // type
return o;
}
};
@@ -233,12 +324,14 @@ inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_f
uint16_t offset = 0,
int64_t default_integer = 0,
double default_real = 0.0,
uint8_t deprecated = 0,
uint8_t required = 0,
uint8_t key = 0) {
bool deprecated = false,
bool required = false,
bool key = false,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
FieldBuilder builder_(_fbb);
builder_.add_default_real(default_real);
builder_.add_default_integer(default_integer);
builder_.add_attributes(attributes);
builder_.add_type(type);
builder_.add_name(name);
builder_.add_offset(offset);
@@ -250,23 +343,35 @@ inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_f
}
struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(4); }
enum {
VT_NAME = 4,
VT_FIELDS = 6,
VT_IS_STRUCT = 8,
VT_MINALIGN = 10,
VT_BYTESIZE = 12,
VT_ATTRIBUTES = 14
};
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
bool KeyCompareLessThan(const Object *o) const { return *name() < *o->name(); }
int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(6); }
uint8_t is_struct() const { return GetField<uint8_t>(8, 0); }
int32_t minalign() const { return GetField<int32_t>(10, 0); }
int32_t bytesize() const { return GetField<int32_t>(12, 0); }
const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(VT_FIELDS); }
bool is_struct() const { return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0; }
int32_t minalign() const { return GetField<int32_t>(VT_MINALIGN, 0); }
int32_t bytesize() const { return GetField<int32_t>(VT_BYTESIZE, 0); }
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* name */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 6 /* fields */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_FIELDS) &&
verifier.Verify(fields()) &&
verifier.VerifyVectorOfTables(fields()) &&
VerifyField<uint8_t>(verifier, 8 /* is_struct */) &&
VerifyField<int32_t>(verifier, 10 /* minalign */) &&
VerifyField<int32_t>(verifier, 12 /* bytesize */) &&
VerifyField<uint8_t>(verifier, VT_IS_STRUCT) &&
VerifyField<int32_t>(verifier, VT_MINALIGN) &&
VerifyField<int32_t>(verifier, VT_BYTESIZE) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
verifier.Verify(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
verifier.EndTable();
}
};
@@ -274,17 +379,18 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct ObjectBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(4, name); }
void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields) { fbb_.AddOffset(6, fields); }
void add_is_struct(uint8_t is_struct) { fbb_.AddElement<uint8_t>(8, is_struct, 0); }
void add_minalign(int32_t minalign) { fbb_.AddElement<int32_t>(10, minalign, 0); }
void add_bytesize(int32_t bytesize) { fbb_.AddElement<int32_t>(12, bytesize, 0); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Object::VT_NAME, name); }
void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields) { fbb_.AddOffset(Object::VT_FIELDS, fields); }
void add_is_struct(bool is_struct) { fbb_.AddElement<uint8_t>(Object::VT_IS_STRUCT, static_cast<uint8_t>(is_struct), 0); }
void add_minalign(int32_t minalign) { fbb_.AddElement<int32_t>(Object::VT_MINALIGN, minalign, 0); }
void add_bytesize(int32_t bytesize) { fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0); }
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes); }
ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
ObjectBuilder &operator=(const ObjectBuilder &);
flatbuffers::Offset<Object> Finish() {
auto o = flatbuffers::Offset<Object>(fbb_.EndTable(start_, 5));
fbb_.Required(o, 4); // name
fbb_.Required(o, 6); // fields
auto o = flatbuffers::Offset<Object>(fbb_.EndTable(start_, 6));
fbb_.Required(o, Object::VT_NAME); // name
fbb_.Required(o, Object::VT_FIELDS); // fields
return o;
}
};
@@ -292,10 +398,12 @@ struct ObjectBuilder {
inline flatbuffers::Offset<Object> CreateObject(flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields = 0,
uint8_t is_struct = 0,
bool is_struct = false,
int32_t minalign = 0,
int32_t bytesize = 0) {
int32_t bytesize = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
ObjectBuilder builder_(_fbb);
builder_.add_attributes(attributes);
builder_.add_bytesize(bytesize);
builder_.add_minalign(minalign);
builder_.add_fields(fields);
@@ -305,24 +413,31 @@ inline flatbuffers::Offset<Object> CreateObject(flatbuffers::FlatBufferBuilder &
}
struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(4); }
const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Enum>> *>(6); }
const flatbuffers::String *file_ident() const { return GetPointer<const flatbuffers::String *>(8); }
const flatbuffers::String *file_ext() const { return GetPointer<const flatbuffers::String *>(10); }
const Object *root_table() const { return GetPointer<const Object *>(12); }
enum {
VT_OBJECTS = 4,
VT_ENUMS = 6,
VT_FILE_IDENT = 8,
VT_FILE_EXT = 10,
VT_ROOT_TABLE = 12
};
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS); }
const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Enum>> *>(VT_ENUMS); }
const flatbuffers::String *file_ident() const { return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT); }
const flatbuffers::String *file_ext() const { return GetPointer<const flatbuffers::String *>(VT_FILE_EXT); }
const Object *root_table() const { return GetPointer<const Object *>(VT_ROOT_TABLE); }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 4 /* objects */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_OBJECTS) &&
verifier.Verify(objects()) &&
verifier.VerifyVectorOfTables(objects()) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, 6 /* enums */) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_ENUMS) &&
verifier.Verify(enums()) &&
verifier.VerifyVectorOfTables(enums()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 8 /* file_ident */) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_FILE_IDENT) &&
verifier.Verify(file_ident()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 10 /* file_ext */) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_FILE_EXT) &&
verifier.Verify(file_ext()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 12 /* root_table */) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ROOT_TABLE) &&
verifier.VerifyTable(root_table()) &&
verifier.EndTable();
}
@@ -331,17 +446,17 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct SchemaBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) { fbb_.AddOffset(4, objects); }
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums) { fbb_.AddOffset(6, enums); }
void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) { fbb_.AddOffset(8, file_ident); }
void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) { fbb_.AddOffset(10, file_ext); }
void add_root_table(flatbuffers::Offset<Object> root_table) { fbb_.AddOffset(12, root_table); }
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) { fbb_.AddOffset(Schema::VT_OBJECTS, objects); }
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums) { fbb_.AddOffset(Schema::VT_ENUMS, enums); }
void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) { fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident); }
void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) { fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext); }
void add_root_table(flatbuffers::Offset<Object> root_table) { fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table); }
SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
SchemaBuilder &operator=(const SchemaBuilder &);
flatbuffers::Offset<Schema> Finish() {
auto o = flatbuffers::Offset<Schema>(fbb_.EndTable(start_, 5));
fbb_.Required(o, 4); // objects
fbb_.Required(o, 6); // enums
fbb_.Required(o, Schema::VT_OBJECTS); // objects
fbb_.Required(o, Schema::VT_ENUMS); // enums
return o;
}
};

View File

@@ -21,6 +21,7 @@
#include <iomanip>
#include <string>
#include <sstream>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#ifdef _WIN32
@@ -34,9 +35,12 @@
#include <winbase.h>
#include <direct.h>
#else
#include <sys/stat.h>
#include <limits.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include "flatbuffers/flatbuffers.h"
namespace flatbuffers {
@@ -68,7 +72,7 @@ template<> inline std::string NumToString<double>(double t) {
auto p = s.find_last_not_of('0');
if (p != std::string::npos) {
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.
}
return s;
@@ -108,33 +112,27 @@ inline int64_t StringToUInt(const char *str, int base = 10) {
#endif
}
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
std::string *dest);
typedef bool (*FileExistsFunction)(const char *filename);
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
FileExistsFunction SetFileExistsFunction(FileExistsFunction
file_exists_function);
// Check if file "name" exists.
inline bool FileExists(const char *name) {
std::ifstream ifs(name);
return ifs.good();
}
bool FileExists(const char *name);
// Check if "name" exists and it is also a directory.
bool DirExists(const char *name);
// Load file "name" into "buf" returning true if successful
// false otherwise. If "binary" is false data is read
// using ifstream's text mode, otherwise data is read with
// no transcoding.
inline bool LoadFile(const char *name, bool binary, std::string *buf) {
std::ifstream ifs(name, binary ? std::ifstream::binary : std::ifstream::in);
if (!ifs.is_open()) return false;
if (binary) {
// The fastest way to read a file into a string.
ifs.seekg(0, std::ios::end);
(*buf).resize(static_cast<size_t>(ifs.tellg()));
ifs.seekg(0, std::ios::beg);
ifs.read(&(*buf)[0], (*buf).size());
} else {
// This is slower, but works correctly on all platforms for text files.
std::ostringstream oss;
oss << ifs.rdbuf();
*buf = oss.str();
}
return !ifs.bad();
}
bool LoadFile(const char *name, bool binary, std::string *buf);
// Save data "buf" of length "len" bytes into a file
// "name" returning true if successful, false otherwise.
@@ -197,8 +195,8 @@ inline std::string StripFileName(const std::string &filepath) {
inline std::string ConCatPathFileName(const std::string &path,
const std::string &filename) {
std::string filepath = path;
if (path.length() && path.back() != kPathSeparator &&
path.back() != kPosixPathSeparator)
if (path.length() && path[path.size() - 1] != kPathSeparator &&
path[path.size() - 1] != kPosixPathSeparator)
filepath += kPathSeparator;
filepath += filename;
return filepath;
@@ -210,7 +208,7 @@ inline void EnsureDirExists(const std::string &filepath) {
auto parent = StripFileName(filepath);
if (parent.length()) EnsureDirExists(parent);
#ifdef _WIN32
_mkdir(filepath.c_str());
(void)_mkdir(filepath.c_str());
#else
mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
#endif
@@ -219,15 +217,19 @@ inline void EnsureDirExists(const std::string &filepath) {
// Obtains the absolute path from any other path.
// Returns the input path if the absolute path couldn't be resolved.
inline std::string AbsolutePath(const std::string &filepath) {
#ifdef _WIN32
char abs_path[MAX_PATH];
return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
#ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
return filepath;
#else
char abs_path[PATH_MAX];
return realpath(filepath.c_str(), abs_path)
#endif
? abs_path
: filepath;
#ifdef _WIN32
char abs_path[MAX_PATH];
return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
#else
char abs_path[PATH_MAX];
return realpath(filepath.c_str(), abs_path)
#endif
? abs_path
: filepath;
#endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
}
// To and from UTF-8 unicode conversion functions