Made all C++ files clang-formatted.

Also added missing generated files.

Change-Id: Ifd22a643a08e3f2edfce92812ed57b87fc0e1875
This commit is contained in:
Wouter van Oortmerssen
2017-12-21 10:54:28 -08:00
parent 5d9930aa0d
commit 89711c9c47
43 changed files with 5850 additions and 5992 deletions

View File

@@ -3,5 +3,11 @@ Language: Cpp
BasedOnStyle: Google BasedOnStyle: Google
DerivePointerAlignment: false DerivePointerAlignment: false
PointerAlignment: Right PointerAlignment: Right
IndentPPDirectives: AfterHash
Cpp11BracedListStyle: false
AlwaysBreakTemplateDeclarations: false
AllowShortCaseLabelsOnASingleLine: true
SpaceAfterTemplateKeyword: false
AllowShortBlocksOnASingleLine: true
... ...

View File

@@ -18,41 +18,43 @@
#include <grpc++/grpc++.h> #include <grpc++/grpc++.h>
#include "monster_test_generated.h"
#include "monster_test.grpc.fb.h" #include "monster_test.grpc.fb.h"
#include "monster_test_generated.h"
using namespace MyGame::Example; using namespace MyGame::Example;
// The callback implementation of our server, that derives from the generated // The callback implementation of our server, that derives from the generated
// code. It implements all rpcs specified in the FlatBuffers schema. // code. It implements all rpcs specified in the FlatBuffers schema.
class ServiceImpl final : public MyGame::Example::MonsterStorage::Service { class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
virtual ::grpc::Status Store(::grpc::ServerContext* context, virtual ::grpc::Status Store(
::grpc::ServerContext *context,
const flatbuffers::grpc::Message<Monster> *request, const flatbuffers::grpc::Message<Monster> *request,
flatbuffers::grpc::Message<Stat> *response) flatbuffers::grpc::Message<Stat> *response) override {
override {
// Create a response from the incoming request name. // Create a response from the incoming request name.
fbb_.Clear(); fbb_.Clear();
auto stat_offset = CreateStat(fbb_, fbb_.CreateString("Hello, " + auto stat_offset = CreateStat(
request->GetRoot()->name()->str())); fbb_, fbb_.CreateString("Hello, " + request->GetRoot()->name()->str()));
fbb_.Finish(stat_offset); fbb_.Finish(stat_offset);
// Transfer ownership of the message to gRPC // Transfer ownership of the message to gRPC
*response = fbb_.ReleaseMessage<Stat>(); *response = fbb_.ReleaseMessage<Stat>();
return grpc::Status::OK; return grpc::Status::OK;
} }
virtual ::grpc::Status Retrieve(::grpc::ServerContext *context, virtual ::grpc::Status Retrieve(
::grpc::ServerContext *context,
const flatbuffers::grpc::Message<Stat> *request, const flatbuffers::grpc::Message<Stat> *request,
::grpc::ServerWriter<flatbuffers::grpc::Message<Monster>> *writer) ::grpc::ServerWriter<flatbuffers::grpc::Message<Monster>> *writer)
override { override {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
fbb_.Clear(); fbb_.Clear();
// Create 10 monsters for resposne. // Create 10 monsters for resposne.
auto monster_offset = auto monster_offset =
CreateMonster(fbb_, 0, 0, 0, fbb_.CreateString( CreateMonster(fbb_, 0, 0, 0,
request->GetRoot()->id()->str() + " No." + std::to_string(i))); fbb_.CreateString(request->GetRoot()->id()->str() +
" No." + std::to_string(i)));
fbb_.Finish(monster_offset); fbb_.Finish(monster_offset);
flatbuffers::grpc::Message<Monster> monster = fbb_.ReleaseMessage<Monster>(); flatbuffers::grpc::Message<Monster> monster =
fbb_.ReleaseMessage<Monster>();
// Send monster to client using streaming. // Send monster to client using streaming.
writer->Write(monster); writer->Write(monster);
@@ -103,7 +105,6 @@ int main(int /*argc*/, const char * /*argv*/[]) {
grpc::InsecureChannelCredentials()); grpc::InsecureChannelCredentials());
auto stub = MyGame::Example::MonsterStorage::NewStub(channel); auto stub = MyGame::Example::MonsterStorage::NewStub(channel);
flatbuffers::grpc::MessageBuilder fbb; flatbuffers::grpc::MessageBuilder fbb;
{ {
grpc::ClientContext context; grpc::ClientContext context;
@@ -149,7 +150,8 @@ int main(int /*argc*/, const char * /*argv*/[]) {
// matches the protobuf gRPC status code for an unparseable message. // matches the protobuf gRPC status code for an unparseable message.
assert(!status.ok()); assert(!status.ok());
assert(status.error_code() == ::grpc::StatusCode::INTERNAL); assert(status.error_code() == ::grpc::StatusCode::INTERNAL);
assert(strcmp(status.error_message().c_str(), "Message verification failed") == 0); assert(strcmp(status.error_message().c_str(),
"Message verification failed") == 0);
} }
#endif #endif

View File

@@ -1,6 +1,7 @@
#ifndef FLATBUFFERS_BASE_H_ #ifndef FLATBUFFERS_BASE_H_
#define FLATBUFFERS_BASE_H_ #define FLATBUFFERS_BASE_H_
// clang-format off
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \ #if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
defined(_MSC_VER) && defined(_DEBUG) defined(_MSC_VER) && defined(_DEBUG)
#define _CRTDBG_MAP_ALLOC #define _CRTDBG_MAP_ALLOC

View File

@@ -71,8 +71,7 @@ class BaseGenerator {
public: public:
virtual bool generate() = 0; virtual bool generate() = 0;
static std::string NamespaceDir(const Parser &parser, static std::string NamespaceDir(const Parser &parser, const std::string &path,
const std::string &path,
const Namespace &ns); const Namespace &ns);
protected: protected:
@@ -128,8 +127,7 @@ struct CommentConfig {
}; };
extern void GenComment(const std::vector<std::string> &dc, extern void GenComment(const std::vector<std::string> &dc,
std::string *code_ptr, std::string *code_ptr, const CommentConfig *config,
const CommentConfig *config,
const char *prefix = ""); const char *prefix = "");
} // namespace flatbuffers } // namespace flatbuffers

View File

@@ -38,6 +38,7 @@ inline void EndianCheck() {
} }
template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() { template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
// clang-format off
#ifdef _MSC_VER #ifdef _MSC_VER
return __alignof(T); return __alignof(T);
#else #else
@@ -47,6 +48,7 @@ template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
return alignof(T); return alignof(T);
#endif #endif
#endif #endif
// clang-format on
} }
// When we read serialized data from memory, in the case of most scalars, // When we read serialized data from memory, in the case of most scalars,
@@ -85,16 +87,15 @@ template<typename T> struct IndirectHelper<const T *> {
// An STL compatible iterator implementation for Vector below, effectively // An STL compatible iterator implementation for Vector below, effectively
// calling Get() for every element. // calling Get() for every element.
template<typename T, typename IT> template<typename T, typename IT> struct VectorIterator {
struct VectorIterator {
typedef std::random_access_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
typedef IT value_type; typedef IT value_type;
typedef uoffset_t difference_type; typedef uoffset_t difference_type;
typedef IT *pointer; typedef IT *pointer;
typedef IT &reference; typedef IT &reference;
VectorIterator(const uint8_t *data, uoffset_t i) : VectorIterator(const uint8_t *data, uoffset_t i)
data_(data + IndirectHelper<T>::element_stride * i) {} : data_(data + IndirectHelper<T>::element_stride * i) {}
VectorIterator(const VectorIterator &other) : data_(other.data_) {} VectorIterator(const VectorIterator &other) : data_(other.data_) {}
VectorIterator &operator=(const VectorIterator &other) { VectorIterator &operator=(const VectorIterator &other) {
@@ -123,13 +124,9 @@ struct VectorIterator {
return (data_ - other.data_) / IndirectHelper<T>::element_stride; return (data_ - other.data_) / IndirectHelper<T>::element_stride;
} }
IT operator *() const { IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
return IndirectHelper<T>::Read(data_, 0);
}
IT operator->() const { IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
return IndirectHelper<T>::Read(data_, 0);
}
VectorIterator &operator++() { VectorIterator &operator++() {
data_ += IndirectHelper<T>::element_stride; data_ += IndirectHelper<T>::element_stride;
@@ -143,7 +140,8 @@ struct VectorIterator {
} }
VectorIterator operator+(const uoffset_t &offset) const { VectorIterator operator+(const uoffset_t &offset) const {
return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, 0); return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride,
0);
} }
VectorIterator &operator+=(const uoffset_t &offset) { VectorIterator &operator+=(const uoffset_t &offset) {
@@ -163,7 +161,8 @@ struct VectorIterator {
} }
VectorIterator operator-(const uoffset_t &offset) { VectorIterator operator-(const uoffset_t &offset) {
return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, 0); return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
0);
} }
VectorIterator &operator-=(const uoffset_t &offset) { VectorIterator &operator-=(const uoffset_t &offset) {
@@ -258,17 +257,15 @@ public:
return reinterpret_cast<const uint8_t *>(&length_ + 1); return reinterpret_cast<const uint8_t *>(&length_ + 1);
} }
uint8_t *Data() { uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
return reinterpret_cast<uint8_t *>(&length_ + 1);
}
// Similarly, but typed, much like std::vector::data // Similarly, but typed, much like std::vector::data
const T *data() const { return reinterpret_cast<const T *>(Data()); } const T *data() const { return reinterpret_cast<const T *>(Data()); }
T *data() { return reinterpret_cast<T *>(Data()); } T *data() { return reinterpret_cast<T *>(Data()); }
template<typename K> return_type LookupByKey(K key) const { template<typename K> return_type LookupByKey(K key) const {
void *search_result = std::bsearch(&key, Data(), size(), void *search_result = std::bsearch(
IndirectHelper<T>::element_stride, KeyCompare<K>); &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
if (!search_result) { if (!search_result) {
return nullptr; // Key not found. return nullptr; // Key not found.
@@ -311,9 +308,8 @@ public:
const uint8_t *Data() const { const uint8_t *Data() const {
return reinterpret_cast<const uint8_t *>(&length_ + 1); return reinterpret_cast<const uint8_t *>(&length_ + 1);
} }
uint8_t *Data() { uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
return reinterpret_cast<uint8_t *>(&length_ + 1);
}
protected: protected:
VectorOfAny(); VectorOfAny();
@@ -399,19 +395,31 @@ class DefaultAllocator : public Allocator {
// the DetachedBuffer can manage the memory lifetime. // the DetachedBuffer can manage the memory lifetime.
class DetachedBuffer { class DetachedBuffer {
public: public:
DetachedBuffer() : allocator_(nullptr), own_allocator_(false), buf_(nullptr), DetachedBuffer()
reserved_(0), cur_(nullptr), size_(0) {} : allocator_(nullptr),
own_allocator_(false),
buf_(nullptr),
reserved_(0),
cur_(nullptr),
size_(0) {}
DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf, DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
size_t reserved, uint8_t *cur, size_t sz) size_t reserved, uint8_t *cur, size_t sz)
: allocator_(allocator), own_allocator_(own_allocator), buf_(buf), : allocator_(allocator),
reserved_(reserved), cur_(cur), size_(sz) { own_allocator_(own_allocator),
buf_(buf),
reserved_(reserved),
cur_(cur),
size_(sz) {
assert(allocator_); assert(allocator_);
} }
DetachedBuffer(DetachedBuffer &&other) DetachedBuffer(DetachedBuffer &&other)
: allocator_(other.allocator_), own_allocator_(other.own_allocator_), : allocator_(other.allocator_),
buf_(other.buf_), reserved_(other.reserved_), cur_(other.cur_), own_allocator_(other.own_allocator_),
buf_(other.buf_),
reserved_(other.reserved_),
cur_(other.cur_),
size_(other.size_) { size_(other.size_) {
other.reset(); other.reset();
} }
@@ -431,22 +439,15 @@ class DetachedBuffer {
return *this; return *this;
} }
~DetachedBuffer() { ~DetachedBuffer() { destroy(); }
destroy();
}
const uint8_t *data() const { const uint8_t *data() const { return cur_; }
return cur_;
}
uint8_t *data() { uint8_t *data() { return cur_; }
return cur_;
}
size_t size() const { size_t size() const { return size_; }
return size_;
}
// clang-format off
#if 0 // disabled for now due to the ordering of classes in this header #if 0 // disabled for now due to the ordering of classes in this header
template <class T> template <class T>
bool Verify() const { bool Verify() const {
@@ -464,6 +465,7 @@ class DetachedBuffer {
return flatbuffers::GetRoot<T>(data()); return flatbuffers::GetRoot<T>(data());
} }
#endif #endif
// clang-format on
// These may change access mode, leave these at end of public section // These may change access mode, leave these at end of public section
FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other)) FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other))
@@ -483,9 +485,7 @@ class DetachedBuffer {
assert(allocator_); assert(allocator_);
allocator_->deallocate(buf_, reserved_); allocator_->deallocate(buf_, reserved_);
} }
if (own_allocator_ && allocator_) { if (own_allocator_ && allocator_) { delete allocator_; }
delete allocator_;
}
reset(); reset();
} }
@@ -509,8 +509,11 @@ class vector_downward {
Allocator *allocator = nullptr, Allocator *allocator = nullptr,
bool own_allocator = false) bool own_allocator = false)
: allocator_(allocator ? allocator : &DefaultAllocator::instance()), : allocator_(allocator ? allocator : &DefaultAllocator::instance()),
own_allocator_(own_allocator), initial_size_(initial_size), reserved_(0), own_allocator_(own_allocator),
buf_(nullptr), cur_(nullptr) { initial_size_(initial_size),
reserved_(0),
buf_(nullptr),
cur_(nullptr) {
assert(allocator_); assert(allocator_);
} }
@@ -519,9 +522,7 @@ class vector_downward {
assert(allocator_); assert(allocator_);
allocator_->deallocate(buf_, reserved_); allocator_->deallocate(buf_, reserved_);
} }
if (own_allocator_ && allocator_) { if (own_allocator_ && allocator_) { delete allocator_; }
delete allocator_;
}
} }
void reset() { void reset() {
@@ -563,9 +564,7 @@ class vector_downward {
uint8_t *make_space(size_t len) { uint8_t *make_space(size_t len) {
assert(cur_ >= buf_); assert(cur_ >= buf_);
if (len > static_cast<size_t>(cur_ - buf_)) { if (len > static_cast<size_t>(cur_ - buf_)) { reallocate(len); }
reallocate(len);
}
cur_ -= len; cur_ -= len;
// Beyond this, signed offsets may not have enough range: // Beyond this, signed offsets may not have enough range:
// (FlatBuffers > 2GB not supported). // (FlatBuffers > 2GB not supported).
@@ -579,9 +578,7 @@ class vector_downward {
return static_cast<uoffset_t>(reserved_ - (cur_ - buf_)); return static_cast<uoffset_t>(reserved_ - (cur_ - buf_));
} }
size_t capacity() const { size_t capacity() const { return reserved_; }
return reserved_;
}
uint8_t *buf() const { uint8_t *buf() const {
assert(buf_); assert(buf_);
@@ -656,7 +653,8 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) {
return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t)); return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
} }
template <typename T, typename Alloc> const T* data(const std::vector<T, Alloc> &v) { template<typename T, typename Alloc>
const T *data(const std::vector<T, Alloc> &v) {
return v.empty() ? nullptr : &v.front(); return v.empty() ? nullptr : &v.front();
} }
template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) { template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
@@ -674,8 +672,7 @@ template <typename T, typename Alloc> T* data(std::vector<T, Alloc> &v) {
/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/ /// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
/// `CreateVector` functions. Do this is depth-first order to build up a tree to /// `CreateVector` functions. Do this is depth-first order to build up a tree to
/// the root. `Finish()` wraps up the buffer ready for transport. /// the root. `Finish()` wraps up the buffer ready for transport.
class FlatBufferBuilder class FlatBufferBuilder {
{
public: public:
/// @brief Default constructor for FlatBufferBuilder. /// @brief Default constructor for FlatBufferBuilder.
/// @param[in] initial_size The initial size of the buffer, in bytes. Defaults /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
@@ -687,9 +684,14 @@ class FlatBufferBuilder
explicit FlatBufferBuilder(size_t initial_size = 1024, explicit FlatBufferBuilder(size_t initial_size = 1024,
Allocator *allocator = nullptr, Allocator *allocator = nullptr,
bool own_allocator = false) bool own_allocator = false)
: buf_(initial_size, allocator, own_allocator), max_voffset_(0), : buf_(initial_size, allocator, own_allocator),
nested(false), finished(false), minalign_(1), force_defaults_(false), max_voffset_(0),
dedup_vtables_(true), string_pool(nullptr) { nested(false),
finished(false),
minalign_(1),
force_defaults_(false),
dedup_vtables_(true),
string_pool(nullptr) {
offsetbuf_.reserve(16); // Avoid first few reallocs. offsetbuf_.reserve(16); // Avoid first few reallocs.
vtables_.reserve(16); vtables_.reserve(16);
EndianCheck(); EndianCheck();
@@ -792,9 +794,7 @@ class FlatBufferBuilder
finished = true; finished = true;
} }
void PushBytes(const uint8_t *bytes, size_t size) { void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
buf_.push(bytes, size);
}
void PopBytes(size_t amount) { buf_.pop(amount); } void PopBytes(size_t amount) { buf_.pop(amount); }
@@ -894,8 +894,8 @@ class FlatBufferBuilder
// by the offsets themselves. In reverse: // by the offsets themselves. In reverse:
// Include space for the last offset and ensure empty tables have a // Include space for the last offset and ensure empty tables have a
// minimum size. // minimum size.
max_voffset_ = (std::max)(static_cast<voffset_t>(max_voffset_ + max_voffset_ =
sizeof(voffset_t)), (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
FieldIndexToOffset(0)); FieldIndexToOffset(0));
buf_.fill_big(max_voffset_); buf_.fill_big(max_voffset_);
auto table_object_size = vtableoffsetloc - start; auto table_object_size = vtableoffsetloc - start;
@@ -905,8 +905,7 @@ class FlatBufferBuilder
WriteScalar<voffset_t>(buf_.data(), max_voffset_); WriteScalar<voffset_t>(buf_.data(), max_voffset_);
// Write the offsets into the table // Write the offsets into the table
for (auto field_location = offsetbuf_.begin(); for (auto field_location = offsetbuf_.begin();
field_location != offsetbuf_.end(); field_location != offsetbuf_.end(); ++field_location) {
++field_location) {
auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off); auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
// If this asserts, it means you've set a field twice. // If this asserts, it means you've set a field twice.
assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id)); assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
@@ -929,9 +928,7 @@ class FlatBufferBuilder
} }
} }
// If this is a new vtable, remember it. // If this is a new vtable, remember it.
if (vt_use == GetSize()) { if (vt_use == GetSize()) { vtables_.push_back(vt_use); }
vtables_.push_back(vt_use);
}
// Fill the vtable offset we created above. // Fill the vtable offset we created above.
// The offset points from the beginning of the object to where the // The offset points from the beginning of the object to where the
// vtable is stored. // vtable is stored.
@@ -1022,8 +1019,7 @@ class FlatBufferBuilder
/// @param[in] str A const reference to a std::string like type with support /// @param[in] str A const reference to a std::string like type with support
/// of T::c_str() and T::length() to store in the buffer. /// of T::c_str() and T::length() to store in the buffer.
/// @return Returns the offset in the buffer where the string starts. /// @return Returns the offset in the buffer where the string starts.
template<typename T> template<typename T> Offset<String> CreateString(const T &str) {
Offset<String> CreateString(const T &str) {
return CreateString(str.c_str(), str.length()); return CreateString(str.c_str(), str.length());
} }
@@ -1119,6 +1115,7 @@ class FlatBufferBuilder
// causing the wrong overload to be selected, remove it. // causing the wrong overload to be selected, remove it.
AssertScalarT<T>(); AssertScalarT<T>();
StartVector(len, sizeof(T)); StartVector(len, sizeof(T));
// clang-format off
#if FLATBUFFERS_LITTLEENDIAN #if FLATBUFFERS_LITTLEENDIAN
PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T)); PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
#else #else
@@ -1130,14 +1127,14 @@ class FlatBufferBuilder
} }
} }
#endif #endif
// clang-format on
return Offset<Vector<T>>(EndVector(len)); return Offset<Vector<T>>(EndVector(len));
} }
template<typename T> Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) { template<typename T>
Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
StartVector(len, sizeof(Offset<T>)); StartVector(len, sizeof(Offset<T>));
for (auto i = len; i > 0; ) { for (auto i = len; i > 0;) { PushElement(v[--i]); }
PushElement(v[--i]);
}
return Offset<Vector<Offset<T>>>(EndVector(len)); return Offset<Vector<Offset<T>>>(EndVector(len));
} }
@@ -1162,6 +1159,7 @@ class FlatBufferBuilder
return Offset<Vector<uint8_t>>(EndVector(v.size())); return Offset<Vector<uint8_t>>(EndVector(v.size()));
} }
// clang-format off
#ifndef FLATBUFFERS_CPP98_STL #ifndef FLATBUFFERS_CPP98_STL
/// @brief Serialize values returned by a function into a FlatBuffer `vector`. /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
/// This is a convenience function that takes care of iteration for you. /// This is a convenience function that takes care of iteration for you.
@@ -1177,6 +1175,7 @@ class FlatBufferBuilder
return CreateVector(elems); return CreateVector(elems);
} }
#endif #endif
// clang-format on
/// @brief Serialize values returned by a function into a FlatBuffer `vector`. /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
/// This is a convenience function that takes care of iteration for you. /// This is a convenience function that takes care of iteration for you.
@@ -1187,8 +1186,8 @@ class FlatBufferBuilder
/// @param state State passed to f. /// @param state State passed to f.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template <typename T, typename F, typename S> Offset<Vector<T>> CreateVector( template<typename T, typename F, typename S>
size_t vector_size, F f, S *state) { Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
std::vector<T> elems(vector_size); std::vector<T> elems(vector_size);
for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state); for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
return CreateVector(elems); return CreateVector(elems);
@@ -1214,8 +1213,8 @@ class FlatBufferBuilder
/// @param[in] len The number of elements to serialize. /// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs( template<typename T>
const T *v, size_t len) { Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>()); StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len); PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
return Offset<Vector<const T *>>(EndVector(len)); return Offset<Vector<const T *>>(EndVector(len));
@@ -1229,8 +1228,9 @@ class FlatBufferBuilder
/// @param[in] len The number of elements to serialize. /// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T, typename S> Offset<Vector<const T *>> CreateVectorOfNativeStructs( template<typename T, typename S>
const S *v, size_t len) { Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
size_t len) {
extern T Pack(const S &); extern T Pack(const S &);
typedef T (*Pack_t)(const S &); typedef T (*Pack_t)(const S &);
std::vector<T> vv(len); std::vector<T> vv(len);
@@ -1238,6 +1238,7 @@ class FlatBufferBuilder
return CreateVectorOfStructs<T>(vv.data(), vv.size()); return CreateVectorOfStructs<T>(vv.data(), vv.size());
} }
// clang-format off
#ifndef FLATBUFFERS_CPP98_STL #ifndef FLATBUFFERS_CPP98_STL
/// @brief Serialize an array of structs into a FlatBuffer `vector`. /// @brief Serialize an array of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements. /// @tparam T The data type of the struct array elements.
@@ -1257,6 +1258,7 @@ class FlatBufferBuilder
return EndVectorOfStructs<T>(vector_size); return EndVectorOfStructs<T>(vector_size);
} }
#endif #endif
// clang-format on
/// @brief Serialize an array of structs into a FlatBuffer `vector`. /// @brief Serialize an array of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements. /// @tparam T The data type of the struct array elements.
@@ -1267,8 +1269,9 @@ class FlatBufferBuilder
/// where the vector is stored. /// where the vector is stored.
/// This is mostly useful when flatbuffers are generated with mutation /// This is mostly useful when flatbuffers are generated with mutation
/// accessors. /// accessors.
template <typename T, typename F, typename S> Offset<Vector<const T *>> template<typename T, typename F, typename S>
CreateVectorOfStructs(size_t vector_size, F f, S *state) { Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
S *state) {
T *structs = StartVectorOfStructs<T>(vector_size); T *structs = StartVectorOfStructs<T>(vector_size);
for (size_t i = 0; i < vector_size; i++) { for (size_t i = 0; i < vector_size; i++) {
f(i, structs, state); f(i, structs, state);
@@ -1283,27 +1286,28 @@ class FlatBufferBuilder
/// serialize into the buffer as a `vector`. /// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T, typename Alloc> Offset<Vector<const T *>> CreateVectorOfStructs( template<typename T, typename Alloc>
Offset<Vector<const T *>> CreateVectorOfStructs(
const std::vector<T, Alloc> &v) { const std::vector<T, Alloc> &v) {
return CreateVectorOfStructs(data(v), v.size()); return CreateVectorOfStructs(data(v), v.size());
} }
/// @brief Serialize a `std::vector` of native structs into a FlatBuffer `vector`. /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
/// `vector`.
/// @tparam T The data type of the `std::vector` struct elements. /// @tparam T The data type of the `std::vector` struct elements.
/// @tparam S The data type of the `std::vector` native struct elements. /// @tparam S The data type of the `std::vector` native struct elements.
/// @param[in]] v A const reference to the `std::vector` of structs to /// @param[in]] v A const reference to the `std::vector` of structs to
/// serialize into the buffer as a `vector`. /// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T, typename S> Offset<Vector<const T *>> CreateVectorOfNativeStructs( template<typename T, typename S>
Offset<Vector<const T *>> CreateVectorOfNativeStructs(
const std::vector<S> &v) { const std::vector<S> &v) {
return CreateVectorOfNativeStructs<T, S>(data(v), v.size()); return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
} }
/// @cond FLATBUFFERS_INTERNAL /// @cond FLATBUFFERS_INTERNAL
template<typename T> template<typename T> struct StructKeyComparator {
struct StructKeyComparator {
bool operator()(const T &a, const T &b) const { bool operator()(const T &a, const T &b) const {
return a.KeyCompareLessThan(&b); return a.KeyCompareLessThan(&b);
} }
@@ -1320,20 +1324,21 @@ class FlatBufferBuilder
/// serialize into the buffer as a `vector`. /// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T> Offset<Vector<const T *>> CreateVectorOfSortedStructs( template<typename T>
std::vector<T> *v) { Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) {
return CreateVectorOfSortedStructs(data(*v), v->size()); return CreateVectorOfSortedStructs(data(*v), v->size());
} }
/// @brief Serialize a `std::vector` of native structs into a FlatBuffer `vector` /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
/// in sorted order. /// `vector` in sorted order.
/// @tparam T The data type of the `std::vector` struct elements. /// @tparam T The data type of the `std::vector` struct elements.
/// @tparam S The data type of the `std::vector` native struct elements. /// @tparam S The data type of the `std::vector` native struct elements.
/// @param[in]] v A const reference to the `std::vector` of structs to /// @param[in]] v A const reference to the `std::vector` of structs to
/// serialize into the buffer as a `vector`. /// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T, typename S> Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs( template<typename T, typename S>
Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
std::vector<S> *v) { std::vector<S> *v) {
return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size()); return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
} }
@@ -1346,14 +1351,14 @@ class FlatBufferBuilder
/// @param[in] len The number of elements to serialize. /// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T> Offset<Vector<const T *>> CreateVectorOfSortedStructs( template<typename T>
T *v, size_t len) { Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
std::sort(v, v + len, StructKeyComparator<T>()); std::sort(v, v + len, StructKeyComparator<T>());
return CreateVectorOfStructs(v, len); return CreateVectorOfStructs(v, len);
} }
/// @brief Serialize an array of native structs into a FlatBuffer `vector` in sorted /// @brief Serialize an array of native structs into a FlatBuffer `vector` in
/// order. /// sorted order.
/// @tparam T The data type of the struct array elements. /// @tparam T The data type of the struct array elements.
/// @tparam S The data type of the native struct array elements. /// @tparam S The data type of the native struct array elements.
/// @param[in] v A pointer to the array of type `S` to serialize into the /// @param[in] v A pointer to the array of type `S` to serialize into the
@@ -1361,8 +1366,9 @@ class FlatBufferBuilder
/// @param[in] len The number of elements to serialize. /// @param[in] len The number of elements to serialize.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T, typename S> Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs( template<typename T, typename S>
S *v, size_t len) { Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
size_t len) {
extern T Pack(const S &); extern T Pack(const S &);
typedef T (*Pack_t)(const S &); typedef T (*Pack_t)(const S &);
std::vector<T> vv(len); std::vector<T> vv(len);
@@ -1371,8 +1377,7 @@ class FlatBufferBuilder
} }
/// @cond FLATBUFFERS_INTERNAL /// @cond FLATBUFFERS_INTERNAL
template<typename T> template<typename T> struct TableKeyComparator {
struct TableKeyComparator {
TableKeyComparator(vector_downward &buf) : buf_(buf) {} TableKeyComparator(vector_downward &buf) : buf_(buf) {}
bool operator()(const Offset<T> &a, const Offset<T> &b) const { bool operator()(const Offset<T> &a, const Offset<T> &b) const {
auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o)); auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
@@ -1394,8 +1399,9 @@ class FlatBufferBuilder
/// @param[in] len The number of elements to store in the `vector`. /// @param[in] len The number of elements to store in the `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables( template<typename T>
Offset<T> *v, size_t len) { Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
size_t len) {
std::sort(v, v + len, TableKeyComparator<T>(buf_)); std::sort(v, v + len, TableKeyComparator<T>(buf_));
return CreateVector(v, len); return CreateVector(v, len);
} }
@@ -1407,7 +1413,8 @@ class FlatBufferBuilder
/// offsets to store in the buffer in sorted order. /// offsets to store in the buffer in sorted order.
/// @return Returns a typed `Offset` into the serialized data indicating /// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored. /// where the vector is stored.
template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables( template<typename T>
Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
std::vector<Offset<T>> *v) { std::vector<Offset<T>> *v) {
return CreateVectorOfSortedTables(data(*v), v->size()); return CreateVectorOfSortedTables(data(*v), v->size());
} }
@@ -1438,8 +1445,8 @@ class FlatBufferBuilder
/// @param[out] buf A pointer to a pointer of type `T` that can be /// @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` /// written to at a later time to serialize the data into a `vector`
/// in the buffer. /// in the buffer.
template<typename T> Offset<Vector<T>> CreateUninitializedVector( template<typename T>
size_t len, T **buf) { Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
return CreateUninitializedVector(len, sizeof(T), return CreateUninitializedVector(len, sizeof(T),
reinterpret_cast<uint8_t **>(buf)); reinterpret_cast<uint8_t **>(buf));
} }
@@ -1458,9 +1465,8 @@ class FlatBufferBuilder
/// @brief Finish serializing a buffer by writing the root offset. /// @brief Finish serializing a buffer by writing the root offset.
/// @param[in] file_identifier If a `file_identifier` is given, the buffer /// @param[in] file_identifier If a `file_identifier` is given, the buffer
/// will be prefixed with a standard FlatBuffers file header. /// will be prefixed with a standard FlatBuffers file header.
template<typename T> void Finish(Offset<T> root, template<typename T>
const char *file_identifier = nullptr) { void Finish(Offset<T> root, const char *file_identifier = nullptr) {
Finish(root.o, file_identifier, false); Finish(root.o, file_identifier, false);
} }
@@ -1471,7 +1477,8 @@ class FlatBufferBuilder
/// All >32 bit quantities in this buffer will be aligned when the whole /// All >32 bit quantities in this buffer will be aligned when the whole
/// size pre-fixed buffer is aligned. /// size pre-fixed buffer is aligned.
/// These kinds of buffers are useful for creating a stream of FlatBuffers. /// These kinds of buffers are useful for creating a stream of FlatBuffers.
template<typename T> void FinishSizePrefixed(Offset<T> root, template<typename T>
void FinishSizePrefixed(Offset<T> root,
const char *file_identifier = nullptr) { const char *file_identifier = nullptr) {
Finish(root.o, file_identifier, true); Finish(root.o, file_identifier, true);
} }
@@ -1484,8 +1491,7 @@ class FlatBufferBuilder
void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) { void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
NotNested(); NotNested();
// This will cause the whole buffer to be aligned. // This will cause the whole buffer to be aligned.
PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
sizeof(uoffset_t) +
(file_identifier ? kFileIdentifierLength : 0), (file_identifier ? kFileIdentifierLength : 0),
minalign_); minalign_);
if (file_identifier) { if (file_identifier) {
@@ -1494,9 +1500,7 @@ class FlatBufferBuilder
kFileIdentifierLength); kFileIdentifierLength);
} }
PushElement(ReferTo(root)); // Location of root. PushElement(ReferTo(root)); // Location of root.
if (size_prefix) { if (size_prefix) { PushElement(GetSize()); }
PushElement(GetSize());
}
finished = true; finished = true;
} }
@@ -1552,8 +1556,8 @@ class FlatBufferBuilder
// End the vector of structues in the flatbuffers. // End the vector of structues in the flatbuffers.
// Vector should have previously be started with StartVectorOfStructs(). // Vector should have previously be started with StartVectorOfStructs().
template<typename T> Offset<Vector<const T *>> EndVectorOfStructs( template<typename T>
size_t vector_size) { Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
return Offset<Vector<const T *>>(EndVector(vector_size)); return Offset<Vector<const T *>>(EndVector(vector_size));
} }
}; };
@@ -1563,7 +1567,8 @@ class FlatBufferBuilder
// Helpers to get a typed pointer to the root object contained in the buffer. // Helpers to get a typed pointer to the root object contained in the buffer.
template<typename T> T *GetMutableRoot(void *buf) { template<typename T> T *GetMutableRoot(void *buf) {
EndianCheck(); EndianCheck();
return reinterpret_cast<T *>(reinterpret_cast<uint8_t *>(buf) + return reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>(buf) +
EndianScalar(*reinterpret_cast<uoffset_t *>(buf))); EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
} }
@@ -1578,18 +1583,17 @@ template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
/// Helpers to get a typed pointer to objects that are currently being built. /// Helpers to get a typed pointer to objects that are currently being built.
/// @warning Creating new objects will lead to reallocations and invalidates /// @warning Creating new objects will lead to reallocations and invalidates
/// the pointer! /// the pointer!
template<typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, template<typename T>
Offset<T> offset) { T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
fbb.GetSize() - offset.o); offset.o);
} }
template<typename T> const T *GetTemporaryPointer(FlatBufferBuilder &fbb, template<typename T>
Offset<T> offset) { const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
return GetMutableTemporaryPointer<T>(fbb, offset); return GetMutableTemporaryPointer<T>(fbb, offset);
} }
/// @brief Get a pointer to the the file_identifier section of the buffer. /// @brief Get a pointer to the the file_identifier section of the buffer.
/// @return Returns a const char pointer to the start of the file_identifier /// @return Returns a const char pointer to the start of the file_identifier
/// characters in the buffer. The returned char * has length /// characters in the buffer. The returned char * has length
@@ -1603,8 +1607,8 @@ inline const char *GetBufferIdentifier(const void *buf) {
// Helper to see if the identifier in a buffer has the expected value. // Helper to see if the identifier in a buffer has the expected value.
inline bool BufferHasIdentifier(const void *buf, const char *identifier) { inline bool BufferHasIdentifier(const void *buf, const char *identifier) {
return strncmp(GetBufferIdentifier(buf), return strncmp(GetBufferIdentifier(buf), identifier,
identifier, FlatBufferBuilder::kFileIdentifierLength) == 0; FlatBufferBuilder::kFileIdentifierLength) == 0;
} }
// Helper class to verify the integrity of a FlatBuffer // Helper class to verify the integrity of a FlatBuffer
@@ -1612,15 +1616,23 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
public: public:
Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64, Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
uoffset_t _max_tables = 1000000) uoffset_t _max_tables = 1000000)
: buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth), : buf_(buf),
num_tables_(0), max_tables_(_max_tables) end_(buf + buf_len),
depth_(0),
max_depth_(_max_depth),
num_tables_(0),
max_tables_(_max_tables)
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
, upper_bound_(buf) , upper_bound_(buf)
#endif #endif
{} // clang-format on
{
}
// Central location where any verification failures register. // Central location where any verification failures register.
bool Check(bool ok) const { bool Check(bool ok) const {
// clang-format off
#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
assert(ok); assert(ok);
#endif #endif
@@ -1628,18 +1640,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
if (!ok) if (!ok)
upper_bound_ = buf_; upper_bound_ = buf_;
#endif #endif
// clang-format on
return ok; return ok;
} }
// Verify any range within the buffer. // Verify any range within the buffer.
bool Verify(const void *elem, size_t elem_len) const { bool Verify(const void *elem, size_t elem_len) const {
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
auto upper_bound = reinterpret_cast<const uint8_t *>(elem) + elem_len; auto upper_bound = reinterpret_cast<const uint8_t *>(elem) + elem_len;
if (upper_bound_ < upper_bound) if (upper_bound_ < upper_bound)
upper_bound_ = upper_bound; upper_bound_ = upper_bound;
#endif #endif
return Check(elem_len <= (size_t) (end_ - buf_) && // clang-format on
elem >= buf_ && return Check(elem_len <= (size_t)(end_ - buf_) && elem >= buf_ &&
elem <= end_ - elem_len); elem <= end_ - elem_len);
} }
@@ -1656,9 +1670,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// Verify a pointer (may be NULL) of any vector type. // Verify a pointer (may be NULL) of any vector type.
template<typename T> bool Verify(const Vector<T> *vec) const { template<typename T> bool Verify(const Vector<T> *vec) const {
const uint8_t *end; const uint8_t *end;
return !vec || return !vec || VerifyVector(reinterpret_cast<const uint8_t *>(vec),
VerifyVector(reinterpret_cast<const uint8_t *>(vec), sizeof(T), sizeof(T), &end);
&end);
} }
// Verify a pointer (may be NULL) of a vector to struct. // Verify a pointer (may be NULL) of a vector to struct.
@@ -1711,8 +1724,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return true; return true;
} }
template<typename T> bool VerifyBufferFromStart(const char *identifier, template<typename T>
const uint8_t *start) { bool VerifyBufferFromStart(const char *identifier, const uint8_t *start) {
if (identifier && if (identifier &&
(size_t(end_ - start) < 2 * sizeof(flatbuffers::uoffset_t) || (size_t(end_ - start) < 2 * sizeof(flatbuffers::uoffset_t) ||
!BufferHasIdentifier(start, identifier))) { !BufferHasIdentifier(start, identifier))) {
@@ -1721,9 +1734,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// Call T::Verify, which must be in the generated code for this type. // Call T::Verify, which must be in the generated code for this type.
auto o = VerifyOffset(start); auto o = VerifyOffset(start);
return o && return o && reinterpret_cast<const T *>(start + o)->Verify(*this)
reinterpret_cast<const T *>(start + o)->
Verify(*this)
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
&& GetComputedSize() && GetComputedSize()
#endif #endif
@@ -1731,9 +1742,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
} }
// Verify this whole buffer, starting with root type T. // Verify this whole buffer, starting with root type T.
template<typename T> bool VerifyBuffer() { template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
return VerifyBuffer<T>(nullptr);
}
template<typename T> bool VerifyBuffer(const char *identifier) { template<typename T> bool VerifyBuffer(const char *identifier) {
return VerifyBufferFromStart<T>(identifier, buf_); return VerifyBufferFromStart<T>(identifier, buf_);
@@ -1768,6 +1777,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return true; return true;
} }
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
// Returns the message size in bytes // Returns the message size in bytes
size_t GetComputedSize() const { size_t GetComputedSize() const {
@@ -1777,6 +1787,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return (buf_ + size > end_) ? 0 : size; return (buf_ + size > end_) ? 0 : size;
} }
#endif #endif
// clang-format on
private: private:
const uint8_t *buf_; const uint8_t *buf_;
@@ -1785,9 +1796,11 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
uoffset_t max_depth_; uoffset_t max_depth_;
uoffset_t num_tables_; uoffset_t num_tables_;
uoffset_t max_tables_; uoffset_t max_tables_;
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
mutable const uint8_t *upper_bound_; mutable const uint8_t *upper_bound_;
#endif #endif
// clang-format on
}; };
// Convenient way to bundle a buffer and its length, to pass it around // Convenient way to bundle a buffer and its length, to pass it around
@@ -1799,7 +1812,9 @@ template<typename T> struct BufferRef : BufferRefBase {
BufferRef(uint8_t *_buf, uoffset_t _len) BufferRef(uint8_t *_buf, uoffset_t _len)
: buf(_buf), len(_len), must_free(false) {} : buf(_buf), len(_len), must_free(false) {}
~BufferRef() { if (must_free) free(buf); } ~BufferRef() {
if (must_free) free(buf);
}
const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); } const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
@@ -1862,8 +1877,7 @@ class Table {
template<typename P> P GetPointer(voffset_t field) { template<typename P> P GetPointer(voffset_t field) {
auto field_offset = GetOptionalFieldOffset(field); auto field_offset = GetOptionalFieldOffset(field);
auto p = data_ + field_offset; auto p = data_ + field_offset;
return field_offset return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
: nullptr; : nullptr;
} }
template<typename P> P GetPointer(voffset_t field) const { template<typename P> P GetPointer(voffset_t field) const {
@@ -1910,15 +1924,14 @@ class Table {
if (!verifier.Verify<soffset_t>(data_)) return false; if (!verifier.Verify<soffset_t>(data_)) return false;
auto vtable = GetVTable(); auto vtable = GetVTable();
// Check the vtable size field, then check vtable fits in its entirety. // Check the vtable size field, then check vtable fits in its entirety.
return verifier.VerifyComplexity() && return verifier.VerifyComplexity() && verifier.Verify<voffset_t>(vtable) &&
verifier.Verify<voffset_t>(vtable) &&
(ReadScalar<voffset_t>(vtable) & (sizeof(voffset_t) - 1)) == 0 && (ReadScalar<voffset_t>(vtable) & (sizeof(voffset_t) - 1)) == 0 &&
verifier.Verify(vtable, ReadScalar<voffset_t>(vtable)); verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
} }
// Verify a particular field. // Verify a particular field.
template<typename T> bool VerifyField(const Verifier &verifier, template<typename T>
voffset_t field) const { bool VerifyField(const Verifier &verifier, voffset_t field) const {
// Calling GetOptionalFieldOffset should be safe now thanks to // Calling GetOptionalFieldOffset should be safe now thanks to
// VerifyTable(). // VerifyTable().
auto field_offset = GetOptionalFieldOffset(field); auto field_offset = GetOptionalFieldOffset(field);
@@ -1927,8 +1940,8 @@ class Table {
} }
// VerifyField for required fields. // VerifyField for required fields.
template<typename T> bool VerifyFieldRequired(const Verifier &verifier, template<typename T>
voffset_t field) const { bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const {
auto field_offset = GetOptionalFieldOffset(field); auto field_offset = GetOptionalFieldOffset(field);
return verifier.Check(field_offset != 0) && return verifier.Check(field_offset != 0) &&
verifier.Verify<T>(data_ + field_offset); verifier.Verify<T>(data_ + field_offset);
@@ -1965,8 +1978,8 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
// Either the vtable is before the root or after the root. // Either the vtable is before the root or after the root.
auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root)); auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
// Align to at least sizeof(uoffset_t). // Align to at least sizeof(uoffset_t).
start = reinterpret_cast<const uint8_t *>( start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
reinterpret_cast<uintptr_t>(start) & ~(sizeof(uoffset_t) - 1)); ~(sizeof(uoffset_t) - 1));
// Additionally, there may be a file_identifier in the buffer, and the root // Additionally, there may be a file_identifier in the buffer, and the root
// offset. The buffer may have been aligned to any size between // offset. The buffer may have been aligned to any size between
// sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align"). // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
@@ -1979,11 +1992,11 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t), static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
"file_identifier is assumed to be the same size as uoffset_t"); "file_identifier is assumed to be the same size as uoffset_t");
for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1; for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
possible_roots; possible_roots; possible_roots--) {
possible_roots--) {
start -= sizeof(uoffset_t); start -= sizeof(uoffset_t);
if (ReadScalar<uoffset_t>(start) + start == if (ReadScalar<uoffset_t>(start) + start ==
reinterpret_cast<const uint8_t *>(root)) return start; reinterpret_cast<const uint8_t *>(root))
return start;
} }
// We didn't find the root, either the "root" passed isn't really a root, // We didn't find the root, either the "root" passed isn't really a root,
// or the buffer is corrupt. // or the buffer is corrupt.
@@ -1996,8 +2009,7 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
// Base class for native objects (FlatBuffer data de-serialized into native // Base class for native objects (FlatBuffer data de-serialized into native
// C++ data structures). // C++ data structures).
// Contains no functionality, purely documentative. // Contains no functionality, purely documentative.
struct NativeTable { struct NativeTable {};
};
/// @brief Function types to be used with resolving hashes into objects and /// @brief Function types to be used with resolving hashes into objects and
/// back again. The resolver gets a pointer to a field inside an object API /// back again. The resolver gets a pointer to a field inside an object API
@@ -2008,6 +2020,7 @@ struct NativeTable {
/// if you wish. The resolver does the opposite lookup, for when the object /// if you wish. The resolver does the opposite lookup, for when the object
/// is being serialized again. /// is being serialized again.
typedef uint64_t hash_value_t; typedef uint64_t hash_value_t;
// clang-format off
#ifdef FLATBUFFERS_CPP98_STL #ifdef FLATBUFFERS_CPP98_STL
typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash); typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
typedef hash_value_t (*rehasher_function_t)(void *pointer); typedef hash_value_t (*rehasher_function_t)(void *pointer);
@@ -2016,6 +2029,7 @@ typedef uint64_t hash_value_t;
resolver_function_t; resolver_function_t;
typedef std::function<hash_value_t (void *pointer)> rehasher_function_t; typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
#endif #endif
// clang-format on
// Helper function to test if a field is present, using any of the field // Helper function to test if a field is present, using any of the field
// enums in the generated code. // enums in the generated code.
@@ -2034,8 +2048,7 @@ template<typename T> bool IsFieldPresent(const T *table, voffset_t field) {
// names must be NULL terminated. // names must be NULL terminated.
inline int LookupEnum(const char **names, const char *name) { inline int LookupEnum(const char **names, const char *name) {
for (const char **p = names; *p; p++) for (const char **p = names; *p; p++)
if (!strcmp(*p, name)) if (!strcmp(*p, name)) return static_cast<int>(p - names);
return static_cast<int>(p - names);
return -1; return -1;
} }
@@ -2049,6 +2062,7 @@ inline int LookupEnum(const char **names, const char *name) {
// by the force_align attribute. // by the force_align attribute.
// These are used in the generated code only. // These are used in the generated code only.
// clang-format off
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define MANUALLY_ALIGNED_STRUCT(alignment) \ #define MANUALLY_ALIGNED_STRUCT(alignment) \
__pragma(pack(1)); \ __pragma(pack(1)); \
@@ -2066,6 +2080,7 @@ inline int LookupEnum(const char **names, const char *name) {
#else #else
#error Unknown compiler, please define structure alignment macros #error Unknown compiler, please define structure alignment macros
#endif #endif
// clang-format on
// Minimal reflection via code generation. // Minimal reflection via code generation.
// Besides full-fat reflection (see reflection.h) and parsing/printing by // Besides full-fat reflection (see reflection.h) and parsing/printing by
@@ -2080,6 +2095,7 @@ inline int LookupEnum(const char **names, const char *name) {
enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM }; enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
// Scalars have the same order as in idl.h // Scalars have the same order as in idl.h
// clang-format off
#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \ #define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
ET(ET_UTYPE) \ ET(ET_UTYPE) \
ET(ET_BOOL) \ ET(ET_BOOL) \
@@ -2110,6 +2126,7 @@ inline const char **ElementaryTypeNames() {
}; };
return names; return names;
} }
// clang-format on
// Basic type info cost just 16bits per field! // Basic type info cost just 16bits per field!
struct TypeCode { struct TypeCode {
@@ -2144,6 +2161,7 @@ struct TypeTable {
// appreciate if you left it in. // appreciate if you left it in.
// Weak linkage is culled by VS & doesn't work on cygwin. // Weak linkage is culled by VS & doesn't work on cygwin.
// clang-format off
#if !defined(_WIN32) && !defined(__CYGWIN__) #if !defined(_WIN32) && !defined(__CYGWIN__)
extern volatile __attribute__((weak)) const char *flatbuffer_version_string; extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
@@ -2190,5 +2208,6 @@ volatile __attribute__((weak)) const char *flatbuffer_version_string =
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning(pop) #pragma warning(pop)
#endif #endif
// clang-format on
#endif // FLATBUFFERS_H_ #endif // FLATBUFFERS_H_

View File

@@ -14,12 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include <functional> #include <functional>
#include <limits> #include <limits>
#include <string> #include <string>
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#ifndef FLATC_H_ #ifndef FLATC_H_
# define FLATC_H_ # define FLATC_H_
@@ -49,12 +49,10 @@ class FlatCompiler {
MakeRuleFn make_rule; MakeRuleFn make_rule;
}; };
typedef void (*WarnFn)(const FlatCompiler *flatc, typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn,
const std::string &warn,
bool show_exe_name); bool show_exe_name);
typedef void (*ErrorFn)(const FlatCompiler *flatc, typedef void (*ErrorFn)(const FlatCompiler *flatc, const std::string &err,
const std::string &err,
bool usage, bool show_exe_name); bool usage, bool show_exe_name);
// Parameters required to initialize the FlatCompiler. // Parameters required to initialize the FlatCompiler.
@@ -78,8 +76,7 @@ class FlatCompiler {
std::string GetUsageString(const char *program_name) const; std::string GetUsageString(const char *program_name) const;
private: private:
void ParseFile(flatbuffers::Parser &parser, void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
const std::string &filename,
const std::string &contents, const std::string &contents,
std::vector<const char *> &include_directories) const; std::vector<const char *> &include_directories) const;
@@ -91,7 +88,6 @@ class FlatCompiler {
InitParams params_; InitParams params_;
}; };
} // namespace flatbuffers } // namespace flatbuffers
#endif // FLATC_H_ #endif // FLATC_H_

View File

@@ -77,7 +77,8 @@ enum Type {
TYPE_VECTOR_FLOAT4 = 24, TYPE_VECTOR_FLOAT4 = 24,
TYPE_BLOB = 25, TYPE_BLOB = 25,
TYPE_BOOL = 26, TYPE_BOOL = 26,
TYPE_VECTOR_BOOL = 36, // To Allow the same type of conversion of type to vector type TYPE_VECTOR_BOOL =
36, // To Allow the same type of conversion of type to vector type
}; };
inline bool IsInline(Type t) { return t <= TYPE_FLOAT || t == TYPE_BOOL; } inline bool IsInline(Type t) { return t <= TYPE_FLOAT || t == TYPE_BOOL; }
@@ -87,7 +88,8 @@ inline bool IsTypedVectorElementType(Type t) {
} }
inline bool IsTypedVector(Type t) { inline bool IsTypedVector(Type t) {
return (t >= TYPE_VECTOR_INT && t <= TYPE_VECTOR_STRING) || t == TYPE_VECTOR_BOOL; return (t >= TYPE_VECTOR_INT && t <= TYPE_VECTOR_STRING) ||
t == TYPE_VECTOR_BOOL;
} }
inline bool IsFixedTypedVector(Type t) { inline bool IsFixedTypedVector(Type t) {
@@ -113,7 +115,8 @@ inline Type ToTypedVectorElementType(Type t) {
inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) { inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) {
assert(IsFixedTypedVector(t)); assert(IsFixedTypedVector(t));
auto fixed_type = t - TYPE_VECTOR_INT2; auto fixed_type = t - TYPE_VECTOR_INT2;
*len = static_cast<uint8_t>(fixed_type / 3 + 2); // 3 types each, starting from length 2. *len = static_cast<uint8_t>(fixed_type / 3 +
2); // 3 types each, starting from length 2.
return static_cast<Type>(fixed_type % 3 + TYPE_INT); return static_cast<Type>(fixed_type % 3 + TYPE_INT);
} }
@@ -130,16 +133,17 @@ typedef int8_t quarter;
template<typename R, typename T1, typename T2, typename T4, typename T8> template<typename R, typename T1, typename T2, typename T4, typename T8>
R ReadSizedScalar(const uint8_t *data, uint8_t byte_width) { R ReadSizedScalar(const uint8_t *data, uint8_t byte_width) {
return byte_width < 4 return byte_width < 4
? (byte_width < 2 ? static_cast<R>(flatbuffers::ReadScalar<T1>(data)) ? (byte_width < 2
? static_cast<R>(flatbuffers::ReadScalar<T1>(data))
: static_cast<R>(flatbuffers::ReadScalar<T2>(data))) : static_cast<R>(flatbuffers::ReadScalar<T2>(data)))
: (byte_width < 8 ? static_cast<R>(flatbuffers::ReadScalar<T4>(data)) : (byte_width < 8
? static_cast<R>(flatbuffers::ReadScalar<T4>(data))
: static_cast<R>(flatbuffers::ReadScalar<T8>(data))); : static_cast<R>(flatbuffers::ReadScalar<T8>(data)));
} }
inline int64_t ReadInt64(const uint8_t *data, uint8_t byte_width) { inline int64_t ReadInt64(const uint8_t *data, uint8_t byte_width) {
return ReadSizedScalar<int64_t, int8_t, int16_t, int32_t, int64_t>(data, return ReadSizedScalar<int64_t, int8_t, int16_t, int32_t, int64_t>(
byte_width); data, byte_width);
} }
inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) { inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
@@ -148,6 +152,7 @@ inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
// TODO: GCC apparently replaces memcpy by a rep movsb, but only if count is a // TODO: GCC apparently replaces memcpy by a rep movsb, but only if count is a
// constant, which here it isn't. Test if memcpy is still faster than // constant, which here it isn't. Test if memcpy is still faster than
// the conditionals in ReadSizedScalar. Can also use inline asm. // the conditionals in ReadSizedScalar. Can also use inline asm.
// clang-format off
#ifdef _MSC_VER #ifdef _MSC_VER
uint64_t u = 0; uint64_t u = 0;
__movsb(reinterpret_cast<uint8_t *>(&u), __movsb(reinterpret_cast<uint8_t *>(&u),
@@ -157,6 +162,7 @@ inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
return ReadSizedScalar<uint64_t, uint8_t, uint16_t, uint32_t, uint64_t>( return ReadSizedScalar<uint64_t, uint8_t, uint16_t, uint32_t, uint64_t>(
data, byte_width); data, byte_width);
#endif #endif
// clang-format on
} }
inline double ReadDouble(const uint8_t *data, uint8_t byte_width) { inline double ReadDouble(const uint8_t *data, uint8_t byte_width) {
@@ -173,7 +179,8 @@ template<typename T> const uint8_t *Indirect(const uint8_t *offset) {
} }
inline BitWidth WidthU(uint64_t u) { inline BitWidth WidthU(uint64_t u) {
#define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width) { \ #define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width) \
{ \
if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \ if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \
} }
FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 8); FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 8);
@@ -216,8 +223,7 @@ class Sized : public Object {
class String : public Sized { class String : public Sized {
public: public:
String(const uint8_t *data, uint8_t byte_width) String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
: Sized(data, byte_width) {}
size_t length() const { return size(); } size_t length() const { return size(); }
const char *c_str() const { return reinterpret_cast<const char *>(data_); } const char *c_str() const { return reinterpret_cast<const char *>(data_); }
@@ -245,8 +251,7 @@ class Blob : public Sized {
class Vector : public Sized { class Vector : public Sized {
public: public:
Vector(const uint8_t *data, uint8_t byte_width) Vector(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
: Sized(data, byte_width) {}
Reference operator[](size_t i) const; Reference operator[](size_t i) const;
@@ -306,8 +311,7 @@ class FixedTypedVector : public Object {
class Map : public Vector { class Map : public Vector {
public: public:
Map(const uint8_t *data, uint8_t byte_width) Map(const uint8_t *data, uint8_t byte_width) : Vector(data, byte_width) {}
: Vector(data, byte_width) {}
Reference operator[](const char *key) const; Reference operator[](const char *key) const;
Reference operator[](const std::string &key) const; Reference operator[](const std::string &key) const;
@@ -330,16 +334,16 @@ class Map : public Vector {
return Map(empty_map + 4, 1); return Map(empty_map + 4, 1);
} }
bool IsTheEmptyMap() const { bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; }
return data_ == EmptyMap().data_;
}
}; };
class Reference { class Reference {
public: public:
Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width, Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
Type type) Type type)
: data_(data), parent_width_(parent_width), byte_width_(byte_width), : data_(data),
parent_width_(parent_width),
byte_width_(byte_width),
type_(type) {} type_(type) {}
Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type) Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type)
@@ -352,13 +356,14 @@ class Reference {
bool IsNull() const { return type_ == TYPE_NULL; } bool IsNull() const { return type_ == TYPE_NULL; }
bool IsBool() const { return type_ == TYPE_BOOL; } bool IsBool() const { return type_ == TYPE_BOOL; }
bool IsInt() const { return type_ == TYPE_INT || bool IsInt() const { return type_ == TYPE_INT || type_ == TYPE_INDIRECT_INT; }
type_ == TYPE_INDIRECT_INT; } bool IsUInt() const {
bool IsUInt() const { return type_ == TYPE_UINT|| return type_ == TYPE_UINT || type_ == TYPE_INDIRECT_UINT;
type_ == TYPE_INDIRECT_UINT;; } }
bool IsIntOrUint() const { return IsInt() || IsUInt(); } bool IsIntOrUint() const { return IsInt() || IsUInt(); }
bool IsFloat() const { return type_ == TYPE_FLOAT || bool IsFloat() const {
type_ == TYPE_INDIRECT_FLOAT; } return type_ == TYPE_FLOAT || type_ == TYPE_INDIRECT_FLOAT;
}
bool IsNumeric() const { return IsIntOrUint() || IsFloat(); } bool IsNumeric() const { return IsIntOrUint() || IsFloat(); }
bool IsString() const { return type_ == TYPE_STRING; } bool IsString() const { return type_ == TYPE_STRING; }
bool IsKey() const { return type_ == TYPE_KEY; } bool IsKey() const { return type_ == TYPE_KEY; }
@@ -367,7 +372,8 @@ class Reference {
bool IsBlob() const { return type_ == TYPE_BLOB; } bool IsBlob() const { return type_ == TYPE_BLOB; }
bool AsBool() const { bool AsBool() const {
return (type_ == TYPE_BOOL ? ReadUInt64(data_, parent_width_) : AsUInt64()) != 0; return (type_ == TYPE_BOOL ? ReadUInt64(data_, parent_width_)
: AsUInt64()) != 0;
} }
// Reads any type as a int64_t. Never fails, does most sensible conversion. // Reads any type as a int64_t. Never fails, does most sensible conversion.
@@ -377,14 +383,15 @@ class Reference {
if (type_ == TYPE_INT) { if (type_ == TYPE_INT) {
// A fast path for the common case. // A fast path for the common case.
return ReadInt64(data_, parent_width_); return ReadInt64(data_, parent_width_);
} else switch (type_) { } else
switch (type_) {
case TYPE_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_); case TYPE_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
case TYPE_UINT: return ReadUInt64(data_, parent_width_); case TYPE_UINT: return ReadUInt64(data_, parent_width_);
case TYPE_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_); case TYPE_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
case TYPE_FLOAT: return static_cast<int64_t>( case TYPE_FLOAT:
ReadDouble(data_, parent_width_)); return static_cast<int64_t>(ReadDouble(data_, parent_width_));
case TYPE_INDIRECT_FLOAT: return static_cast<int64_t>( case TYPE_INDIRECT_FLOAT:
ReadDouble(Indirect(), byte_width_)); return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_));
case TYPE_NULL: return 0; case TYPE_NULL: return 0;
case TYPE_STRING: return flatbuffers::StringToInt(AsString().c_str()); case TYPE_STRING: return flatbuffers::StringToInt(AsString().c_str());
case TYPE_VECTOR: return static_cast<int64_t>(AsVector().size()); case TYPE_VECTOR: return static_cast<int64_t>(AsVector().size());
@@ -405,14 +412,15 @@ class Reference {
if (type_ == TYPE_UINT) { if (type_ == TYPE_UINT) {
// A fast path for the common case. // A fast path for the common case.
return ReadUInt64(data_, parent_width_); return ReadUInt64(data_, parent_width_);
} else switch (type_) { } else
switch (type_) {
case TYPE_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_); case TYPE_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
case TYPE_INT: return ReadInt64(data_, parent_width_); case TYPE_INT: return ReadInt64(data_, parent_width_);
case TYPE_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_); case TYPE_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
case TYPE_FLOAT: return static_cast<uint64_t>( case TYPE_FLOAT:
ReadDouble(data_, parent_width_)); return static_cast<uint64_t>(ReadDouble(data_, parent_width_));
case TYPE_INDIRECT_FLOAT: return static_cast<uint64_t>( case TYPE_INDIRECT_FLOAT:
ReadDouble(Indirect(), byte_width_)); return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_));
case TYPE_NULL: return 0; case TYPE_NULL: return 0;
case TYPE_STRING: return flatbuffers::StringToUInt(AsString().c_str()); case TYPE_STRING: return flatbuffers::StringToUInt(AsString().c_str());
case TYPE_VECTOR: return static_cast<uint64_t>(AsVector().size()); case TYPE_VECTOR: return static_cast<uint64_t>(AsVector().size());
@@ -431,21 +439,22 @@ class Reference {
if (type_ == TYPE_FLOAT) { if (type_ == TYPE_FLOAT) {
// A fast path for the common case. // A fast path for the common case.
return ReadDouble(data_, parent_width_); return ReadDouble(data_, parent_width_);
} else switch (type_) { } else
switch (type_) {
case TYPE_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_); case TYPE_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_);
case TYPE_INT: return static_cast<double>( case TYPE_INT:
ReadInt64(data_, parent_width_)); return static_cast<double>(ReadInt64(data_, parent_width_));
case TYPE_UINT: return static_cast<double>( case TYPE_UINT:
ReadUInt64(data_, parent_width_)); return static_cast<double>(ReadUInt64(data_, parent_width_));
case TYPE_INDIRECT_INT: return static_cast<double>( case TYPE_INDIRECT_INT:
ReadInt64(Indirect(), byte_width_)); return static_cast<double>(ReadInt64(Indirect(), byte_width_));
case TYPE_INDIRECT_UINT: return static_cast<double>( case TYPE_INDIRECT_UINT:
ReadUInt64(Indirect(), byte_width_)); return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
case TYPE_NULL: return 0.0; case TYPE_NULL: return 0.0;
case TYPE_STRING: return strtod(AsString().c_str(), nullptr); case TYPE_STRING: return strtod(AsString().c_str(), nullptr);
case TYPE_VECTOR: return static_cast<double>(AsVector().size()); case TYPE_VECTOR: return static_cast<double>(AsVector().size());
case TYPE_BOOL: return static_cast<double>( case TYPE_BOOL:
ReadUInt64(data_, parent_width_)); return static_cast<double>(ReadUInt64(data_, parent_width_));
default: default:
// Convert strings and other things to float. // Convert strings and other things to float.
return 0; return 0;
@@ -652,9 +661,7 @@ class Reference {
memcpy(const_cast<char *>(s.c_str()), str, len); memcpy(const_cast<char *>(s.c_str()), str, len);
return true; return true;
} }
bool MutateString(const char *str) { bool MutateString(const char *str) { return MutateString(str, strlen(str)); }
return MutateString(str, strlen(str));
}
bool MutateString(const std::string &str) { bool MutateString(const std::string &str) {
return MutateString(str.data(), str.length()); return MutateString(str.data(), str.length());
} }
@@ -664,9 +671,11 @@ class Reference {
return flexbuffers::Indirect(data_, parent_width_); return flexbuffers::Indirect(data_, parent_width_);
} }
template<typename T> bool Mutate(const uint8_t *dest, T t, size_t byte_width, template<typename T>
bool Mutate(const uint8_t *dest, T t, size_t byte_width,
BitWidth value_width) { BitWidth value_width) {
auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <= byte_width; auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <=
byte_width;
if (fits) { if (fits) {
t = flatbuffers::EndianScalar(t); t = flatbuffers::EndianScalar(t);
memcpy(const_cast<uint8_t *>(dest), &t, byte_width); memcpy(const_cast<uint8_t *>(dest), &t, byte_width);
@@ -674,7 +683,8 @@ class Reference {
return fits; return fits;
} }
template<typename T> bool MutateF(const uint8_t *dest, T t, size_t byte_width, template<typename T>
bool MutateF(const uint8_t *dest, T t, size_t byte_width,
BitWidth value_width) { BitWidth value_width) {
if (byte_width == sizeof(double)) if (byte_width == sizeof(double))
return Mutate(dest, static_cast<double>(t), byte_width, value_width); return Mutate(dest, static_cast<double>(t), byte_width, value_width);
@@ -707,21 +717,25 @@ template<> inline double Reference::As<double>() { return AsDouble(); }
template<> inline float Reference::As<float>() { return AsFloat(); } template<> inline float Reference::As<float>() { return AsFloat(); }
template<> inline String Reference::As<String>() { return AsString(); } template<> inline String Reference::As<String>() { return AsString(); }
template<> inline std::string Reference::As<std::string>() { return AsString().str(); } template<> inline std::string Reference::As<std::string>() {
return AsString().str();
}
template<> inline Blob Reference::As<Blob>() { return AsBlob(); } template<> inline Blob Reference::As<Blob>() { return AsBlob(); }
template<> inline Vector Reference::As<Vector>() { return AsVector(); } template<> inline Vector Reference::As<Vector>() { return AsVector(); }
template<> inline TypedVector Reference::As<TypedVector>() { return AsTypedVector(); } template<> inline TypedVector Reference::As<TypedVector>() {
template<> inline FixedTypedVector Reference::As<FixedTypedVector>() { return AsFixedTypedVector(); } return AsTypedVector();
}
template<> inline FixedTypedVector Reference::As<FixedTypedVector>() {
return AsFixedTypedVector();
}
template<> inline Map Reference::As<Map>() { return AsMap(); } template<> inline Map Reference::As<Map>() { return AsMap(); }
inline uint8_t PackedType(BitWidth bit_width, Type type) { inline uint8_t PackedType(BitWidth bit_width, Type type) {
return static_cast<uint8_t>(bit_width | (type << 2)); return static_cast<uint8_t>(bit_width | (type << 2));
} }
inline uint8_t NullPackedType() { inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, TYPE_NULL); }
return PackedType(BIT_WIDTH_8, TYPE_NULL);
}
// Vector accessors. // Vector accessors.
// Note: if you try to access outside of bounds, you get a Null value back // Note: if you try to access outside of bounds, you get a Null value back
@@ -770,8 +784,7 @@ inline Reference Map::operator[](const char *key) const {
case 8: comp = KeyCompare<uint64_t>; break; case 8: comp = KeyCompare<uint64_t>; break;
} }
auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp); auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp);
if (!res) if (!res) return Reference(nullptr, 1, NullPackedType());
return Reference(nullptr, 1, NullPackedType());
auto i = (reinterpret_cast<uint8_t *>(res) - keys.data_) / keys.byte_width_; auto i = (reinterpret_cast<uint8_t *>(res) - keys.data_) / keys.byte_width_;
return (*static_cast<const Vector *>(this))[i]; return (*static_cast<const Vector *>(this))[i];
} }
@@ -817,8 +830,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
public: public:
Builder(size_t initial_size = 256, Builder(size_t initial_size = 256,
BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS) BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS)
: buf_(initial_size), finished_(false), flags_(flags), : buf_(initial_size),
force_min_bit_width_(BIT_WIDTH_8), key_pool(KeyOffsetCompare(buf_)), finished_(false),
flags_(flags),
force_min_bit_width_(BIT_WIDTH_8),
key_pool(KeyOffsetCompare(buf_)),
string_pool(StringOffsetCompare(buf_)) { string_pool(StringOffsetCompare(buf_)) {
buf_.clear(); buf_.clear();
} }
@@ -831,9 +847,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
} }
// Size of the buffer. Does not include unfinished values. // Size of the buffer. Does not include unfinished values.
size_t GetSize() const { size_t GetSize() const { return buf_.size(); }
return buf_.size();
}
// Reset all state so we can re-use the buffer. // Reset all state so we can re-use the buffer.
void Clear() { void Clear() {
@@ -851,26 +865,42 @@ class Builder FLATBUFFERS_FINAL_CLASS {
// vectors and elsewhere). // vectors and elsewhere).
void Null() { stack_.push_back(Value()); } void Null() { stack_.push_back(Value()); }
void Null(const char *key) { Key(key); Null(); } void Null(const char *key) {
Key(key);
Null();
}
void Int(int64_t i) { stack_.push_back(Value(i, TYPE_INT, WidthI(i))); } void Int(int64_t i) { stack_.push_back(Value(i, TYPE_INT, WidthI(i))); }
void Int(const char *key, int64_t i) { Key(key); Int(i); } void Int(const char *key, int64_t i) {
Key(key);
Int(i);
}
void UInt(uint64_t u) { stack_.push_back(Value(u, TYPE_UINT, WidthU(u))); } void UInt(uint64_t u) { stack_.push_back(Value(u, TYPE_UINT, WidthU(u))); }
void UInt(const char *key, uint64_t u) { Key(key); Int(u); } void UInt(const char *key, uint64_t u) {
Key(key);
Int(u);
}
void Float(float f) { stack_.push_back(Value(f)); } void Float(float f) { stack_.push_back(Value(f)); }
void Float(const char *key, float f) { Key(key); Float(f); } void Float(const char *key, float f) {
Key(key);
Float(f);
}
void Double(double f) { stack_.push_back(Value(f)); } void Double(double f) { stack_.push_back(Value(f)); }
void Double(const char *key, double d) { Key(key); Double(d); } void Double(const char *key, double d) {
Key(key);
Double(d);
}
void Bool(bool b) { stack_.push_back(Value(b)); } void Bool(bool b) { stack_.push_back(Value(b)); }
void Bool(const char *key, bool b) { Key(key); Bool(b); } void Bool(const char *key, bool b) {
Key(key);
void IndirectInt(int64_t i) { Bool(b);
PushIndirect(i, TYPE_INDIRECT_INT, WidthI(i));
} }
void IndirectInt(int64_t i) { PushIndirect(i, TYPE_INDIRECT_INT, WidthI(i)); }
void IndirectInt(const char *key, int64_t i) { void IndirectInt(const char *key, int64_t i) {
Key(key); Key(key);
IndirectInt(i); IndirectInt(i);
@@ -939,9 +969,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
} }
return sloc; return sloc;
} }
size_t String(const char *str) { size_t String(const char *str) { return String(str, strlen(str)); }
return String(str, strlen(str));
}
size_t String(const std::string &str) { size_t String(const std::string &str) {
return String(str.c_str(), str.size()); return String(str.c_str(), str.size());
} }
@@ -974,9 +1002,15 @@ class Builder FLATBUFFERS_FINAL_CLASS {
// Also some FlatBuffers types? // Also some FlatBuffers types?
size_t StartVector() { return stack_.size(); } size_t StartVector() { return stack_.size(); }
size_t StartVector(const char *key) { Key(key); return stack_.size(); } size_t StartVector(const char *key) {
Key(key);
return stack_.size();
}
size_t StartMap() { return stack_.size(); } size_t StartMap() { return stack_.size(); }
size_t StartMap(const char *key) { Key(key); return stack_.size(); } size_t StartMap(const char *key) {
Key(key);
return stack_.size();
}
// TODO(wvo): allow this to specify an aligment greater than the natural // TODO(wvo): allow this to specify an aligment greater than the natural
// alignment. // alignment.
@@ -1000,7 +1034,10 @@ class Builder FLATBUFFERS_FINAL_CLASS {
} }
// Now sort values, so later we can do a binary seach lookup. // Now sort values, so later we can do a binary seach lookup.
// We want to sort 2 array elements at a time. // We want to sort 2 array elements at a time.
struct TwoValue { Value key; Value val; }; struct TwoValue {
Value key;
Value val;
};
// TODO(wvo): strict aliasing? // TODO(wvo): strict aliasing?
// TODO(wvo): allow the caller to indicate the data is already sorted // TODO(wvo): allow the caller to indicate the data is already sorted
// for maximum efficiency? With an assert to check sortedness to make sure // for maximum efficiency? With an assert to check sortedness to make sure
@@ -1011,8 +1048,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
// sorted fashion. // sorted fashion.
// std::sort is typically already a lot faster on sorted data though. // std::sort is typically already a lot faster on sorted data though.
auto dict = auto dict =
reinterpret_cast<TwoValue *>(flatbuffers::vector_data(stack_) + reinterpret_cast<TwoValue *>(flatbuffers::vector_data(stack_) + start);
start);
std::sort(dict, dict + len, std::sort(dict, dict + len,
[&](const TwoValue &a, const TwoValue &b) -> bool { [&](const TwoValue &a, const TwoValue &b) -> bool {
auto as = reinterpret_cast<const char *>( auto as = reinterpret_cast<const char *>(
@@ -1020,10 +1056,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
auto bs = reinterpret_cast<const char *>( auto bs = reinterpret_cast<const char *>(
flatbuffers::vector_data(buf_) + b.key.u_); flatbuffers::vector_data(buf_) + b.key.u_);
auto comp = strcmp(as, bs); auto comp = strcmp(as, bs);
// If this assertion hits, you've added two keys with the same value to // If this assertion hits, you've added two keys with the same
// this map. // value to this map.
// TODO: Have to check for pointer equality, as some sort implementation // TODO: Have to check for pointer equality, as some sort
// apparently call this function with the same element?? Why? // implementation apparently call this function with the same
// element?? Why?
assert(comp || &a == &b); assert(comp || &a == &b);
return comp < 0; return comp < 0;
}); });
@@ -1053,8 +1090,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
f(); f();
return EndVector(start, false, false); return EndVector(start, false, false);
} }
template <typename F, typename T> size_t Vector(const char *key, F f, template<typename F, typename T>
T &state) { size_t Vector(const char *key, F f, T &state) {
auto start = StartVector(key); auto start = StartVector(key);
f(state); f(state);
return EndVector(start, false, false); return EndVector(start, false, false);
@@ -1070,8 +1107,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
EndVector(start, false, false); EndVector(start, false, false);
} }
} }
template<typename T> void Vector(const char *key, const T *elems, template<typename T>
size_t len) { void Vector(const char *key, const T *elems, size_t len) {
Key(key); Key(key);
Vector(elems, len); Vector(elems, len);
} }
@@ -1094,8 +1131,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
f(); f();
return EndVector(start, true, false); return EndVector(start, true, false);
} }
template <typename F, typename T> size_t TypedVector(const char *key, F f, template<typename F, typename T>
T &state) { size_t TypedVector(const char *key, F f, T &state) {
auto start = StartVector(key); auto start = StartVector(key);
f(state); f(state);
return EndVector(start, true, false); return EndVector(start, true, false);
@@ -1110,8 +1147,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
return ScalarVector(elems, len, true); return ScalarVector(elems, len, true);
} }
template<typename T> size_t FixedTypedVector(const char *key, const T *elems, template<typename T>
size_t len) { size_t FixedTypedVector(const char *key, const T *elems, size_t len) {
Key(key); Key(key);
return FixedTypedVector(elems, len); return FixedTypedVector(elems, len);
} }
@@ -1131,8 +1168,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
f(); f();
return EndMap(start); return EndMap(start);
} }
template <typename F, typename T> size_t Map(const char *key, F f, template<typename F, typename T> size_t Map(const char *key, F f, T &state) {
T &state) {
auto start = StartMap(key); auto start = StartMap(key);
f(state); f(state);
return EndMap(start); return EndMap(start);
@@ -1160,9 +1196,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
void Add(const std::string &str) { String(str); } void Add(const std::string &str) { String(str); }
void Add(const flexbuffers::String &str) { String(str); } void Add(const flexbuffers::String &str) { String(str); }
template<typename T> void Add(const std::vector<T> &vec) { template<typename T> void Add(const std::vector<T> &vec) { Vector(vec); }
Vector(vec);
}
template<typename T> void Add(const char *key, const T &t) { template<typename T> void Add(const char *key, const T &t) {
Key(key); Key(key);
@@ -1173,9 +1207,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
Map(map); Map(map);
} }
template<typename T> void operator+=(const T &t) { template<typename T> void operator+=(const T &t) { Add(t); }
Add(t);
}
// This function is useful in combination with the Mutate* functions above. // This function is useful in combination with the Mutate* functions above.
// It forces elements of vectors and maps to have a minimum size, such that // It forces elements of vectors and maps to have a minimum size, such that
@@ -1220,8 +1252,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
} }
void WriteBytes(const void *val, size_t size) { void WriteBytes(const void *val, size_t size) {
buf_.insert(buf_.end(), buf_.insert(buf_.end(), reinterpret_cast<const uint8_t *>(val),
reinterpret_cast<const uint8_t *>(val),
reinterpret_cast<const uint8_t *>(val) + size); reinterpret_cast<const uint8_t *>(val) + size);
} }
@@ -1268,8 +1299,10 @@ class Builder FLATBUFFERS_FINAL_CLASS {
assert(flatbuffers::is_scalar<T>::value); assert(flatbuffers::is_scalar<T>::value);
return flatbuffers::is_floating_point<T>::value return flatbuffers::is_floating_point<T>::value
? TYPE_FLOAT ? TYPE_FLOAT
: flatbuffers::is_same<T, bool>::value ? TYPE_BOOL : flatbuffers::is_same<T, bool>::value
: (flatbuffers::is_unsigned<T>::value ? TYPE_UINT : TYPE_INT); ? TYPE_BOOL
: (flatbuffers::is_unsigned<T>::value ? TYPE_UINT
: TYPE_INT);
} }
struct Value { struct Value {
@@ -1286,17 +1319,18 @@ class Builder FLATBUFFERS_FINAL_CLASS {
Value() : i_(0), type_(TYPE_NULL), min_bit_width_(BIT_WIDTH_8) {} Value() : i_(0), type_(TYPE_NULL), min_bit_width_(BIT_WIDTH_8) {}
Value(bool b) : u_(static_cast<uint64_t>(b)), type_(TYPE_BOOL), min_bit_width_(BIT_WIDTH_8) {} Value(bool b)
: u_(static_cast<uint64_t>(b)),
type_(TYPE_BOOL),
min_bit_width_(BIT_WIDTH_8) {}
Value(int64_t i, Type t, BitWidth bw) Value(int64_t i, Type t, BitWidth bw)
: i_(i), type_(t), min_bit_width_(bw) {} : i_(i), type_(t), min_bit_width_(bw) {}
Value(uint64_t u, Type t, BitWidth bw) Value(uint64_t u, Type t, BitWidth bw)
: u_(u), type_(t), min_bit_width_(bw) {} : u_(u), type_(t), min_bit_width_(bw) {}
Value(float f) Value(float f) : f_(f), type_(TYPE_FLOAT), min_bit_width_(BIT_WIDTH_32) {}
: f_(f), type_(TYPE_FLOAT), min_bit_width_(BIT_WIDTH_32) {} Value(double f) : f_(f), type_(TYPE_FLOAT), min_bit_width_(WidthF(f)) {}
Value(double f)
: f_(f), type_(TYPE_FLOAT), min_bit_width_(WidthF(f)) {}
uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const { uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
return PackedType(StoredWidth(parent_bit_width_), type_); return PackedType(StoredWidth(parent_bit_width_), type_);
@@ -1315,15 +1349,15 @@ class Builder FLATBUFFERS_FINAL_CLASS {
byte_width <= sizeof(flatbuffers::largest_scalar_t); byte_width <= sizeof(flatbuffers::largest_scalar_t);
byte_width *= 2) { byte_width *= 2) {
// Where are we going to write this offset? // Where are we going to write this offset?
auto offset_loc = auto offset_loc = buf_size +
buf_size +
flatbuffers::PaddingBytes(buf_size, byte_width) + flatbuffers::PaddingBytes(buf_size, byte_width) +
elem_index * byte_width; elem_index * byte_width;
// Compute relative offset. // Compute relative offset.
auto offset = offset_loc - u_; auto offset = offset_loc - u_;
// Does it fit? // Does it fit?
auto bit_width = WidthU(offset); auto bit_width = WidthU(offset);
if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) == byte_width) if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) ==
byte_width)
return bit_width; return bit_width;
} }
assert(false); // Must match one of the sizes above. assert(false); // Must match one of the sizes above.
@@ -1343,19 +1377,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
void WriteAny(const Value &val, uint8_t byte_width) { void WriteAny(const Value &val, uint8_t byte_width) {
switch (val.type_) { switch (val.type_) {
case TYPE_NULL: case TYPE_NULL:
case TYPE_INT: case TYPE_INT: Write(val.i_, byte_width); break;
Write(val.i_, byte_width);
break;
case TYPE_BOOL: case TYPE_BOOL:
case TYPE_UINT: case TYPE_UINT: Write(val.u_, byte_width); break;
Write(val.u_, byte_width); case TYPE_FLOAT: WriteDouble(val.f_, byte_width); break;
break; default: WriteOffset(val.u_, byte_width); break;
case TYPE_FLOAT:
WriteDouble(val.f_, byte_width);
break;
default:
WriteOffset(val.u_, byte_width);
break;
} }
} }
@@ -1369,8 +1395,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
return sloc; return sloc;
} }
template<typename T> size_t ScalarVector(const T *elems, size_t len, template<typename T>
bool fixed) { size_t ScalarVector(const T *elems, size_t len, bool fixed) {
auto vector_type = GetScalarType<T>(); auto vector_type = GetScalarType<T>();
auto byte_width = sizeof(T); auto byte_width = sizeof(T);
auto bit_width = WidthB(byte_width); auto bit_width = WidthB(byte_width);
@@ -1436,10 +1462,9 @@ class Builder FLATBUFFERS_FINAL_CLASS {
buf_.push_back(stack_[i].StoredPackedType(bit_width)); buf_.push_back(stack_[i].StoredPackedType(bit_width));
} }
} }
return Value(static_cast<uint64_t>(vloc), keys return Value(static_cast<uint64_t>(vloc),
? TYPE_MAP keys ? TYPE_MAP
: (typed : (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0)
? ToTypedVector(vector_type, fixed ? vec_len : 0)
: TYPE_VECTOR), : TYPE_VECTOR),
bit_width); bit_width);
} }
@@ -1473,10 +1498,10 @@ class Builder FLATBUFFERS_FINAL_CLASS {
struct StringOffsetCompare { struct StringOffsetCompare {
StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {} StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
bool operator()(const StringOffset &a, const StringOffset &b) const { bool operator()(const StringOffset &a, const StringOffset &b) const {
auto stra = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + auto stra = reinterpret_cast<const char *>(
a.first); flatbuffers::vector_data(*buf_) + a.first);
auto strb = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + auto strb = reinterpret_cast<const char *>(
b.first); flatbuffers::vector_data(*buf_) + b.first);
return strncmp(stra, strb, (std::min)(a.second, b.second) + 1) < 0; return strncmp(stra, strb, (std::min)(a.second, b.second) + 1) < 0;
} }
const std::vector<uint8_t> *buf_; const std::vector<uint8_t> *buf_;

View File

@@ -30,8 +30,7 @@ namespace grpc {
// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify` // `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer // and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
// is refcounted and ownership is be managed automatically. // is refcounted and ownership is be managed automatically.
template <class T> template<class T> class Message {
class Message {
public: public:
Message() : slice_(grpc_empty_slice()) {} Message() : slice_(grpc_empty_slice()) {}
@@ -137,7 +136,7 @@ namespace detail {
struct SliceAllocatorMember { struct SliceAllocatorMember {
SliceAllocator slice_allocator_; SliceAllocator slice_allocator_;
}; };
} } // namespace detail
// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator // MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
// to allocate gRPC buffers. // to allocate gRPC buffers.
@@ -155,8 +154,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
// GetMessage extracts the subslice of the buffer corresponding to the // GetMessage extracts the subslice of the buffer corresponding to the
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer // flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
// ownership. // ownership.
template <class T> template<class T> Message<T> GetMessage() {
Message<T> GetMessage() {
auto buf_data = buf_.buf(); // pointer to memory auto buf_data = buf_.buf(); // pointer to memory
auto buf_size = buf_.capacity(); // size of memory auto buf_size = buf_.capacity(); // size of memory
auto msg_data = buf_.data(); // pointer to msg auto msg_data = buf_.data(); // pointer to msg
@@ -178,8 +176,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
return msg; return msg;
} }
template <class T> template<class T> Message<T> ReleaseMessage() {
Message<T> ReleaseMessage() {
Message<T> msg = GetMessage<T>(); Message<T> msg = GetMessage<T>();
Reset(); Reset();
return msg; return msg;
@@ -194,8 +191,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
namespace grpc { namespace grpc {
template <class T> template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
class SerializationTraits<flatbuffers::grpc::Message<T>> {
public: public:
static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg, static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg,
grpc_byte_buffer **buffer, bool *own_buffer) { grpc_byte_buffer **buffer, bool *own_buffer) {
@@ -250,6 +246,6 @@ class SerializationTraits<flatbuffers::grpc::Message<T>> {
} }
}; };
} // namespace grpc; } // namespace grpc
#endif // FLATBUFFERS_GRPC_H_ #endif // FLATBUFFERS_GRPC_H_

View File

@@ -24,26 +24,22 @@
namespace flatbuffers { namespace flatbuffers {
template <typename T> template<typename T> struct FnvTraits {
struct FnvTraits {
static const T kFnvPrime; static const T kFnvPrime;
static const T kOffsetBasis; static const T kOffsetBasis;
}; };
template <> template<> struct FnvTraits<uint32_t> {
struct FnvTraits<uint32_t> {
static const uint32_t kFnvPrime = 0x01000193; static const uint32_t kFnvPrime = 0x01000193;
static const uint32_t kOffsetBasis = 0x811C9DC5; static const uint32_t kOffsetBasis = 0x811C9DC5;
}; };
template <> template<> struct FnvTraits<uint64_t> {
struct FnvTraits<uint64_t> {
static const uint64_t kFnvPrime = 0x00000100000001b3ULL; static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL; static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
}; };
template <typename T> template<typename T> T HashFnv1(const char *input) {
T HashFnv1(const char *input) {
T hash = FnvTraits<T>::kOffsetBasis; T hash = FnvTraits<T>::kOffsetBasis;
for (const char *c = input; *c; ++c) { for (const char *c = input; *c; ++c) {
hash *= FnvTraits<T>::kFnvPrime; hash *= FnvTraits<T>::kFnvPrime;
@@ -52,8 +48,7 @@ T HashFnv1(const char *input) {
return hash; return hash;
} }
template <typename T> template<typename T> T HashFnv1a(const char *input) {
T HashFnv1a(const char *input) {
T hash = FnvTraits<T>::kOffsetBasis; T hash = FnvTraits<T>::kOffsetBasis;
for (const char *c = input; *c; ++c) { for (const char *c = input; *c; ++c) {
hash ^= static_cast<unsigned char>(*c); hash ^= static_cast<unsigned char>(*c);
@@ -62,8 +57,7 @@ T HashFnv1a(const char *input) {
return hash; return hash;
} }
template <typename T> template<typename T> struct NamedHashFunction {
struct NamedHashFunction {
const char *name; const char *name;
typedef T (*HashFunction)(const char *); typedef T (*HashFunction)(const char *);

View File

@@ -18,14 +18,14 @@
#define FLATBUFFERS_IDL_H_ #define FLATBUFFERS_IDL_H_
#include <map> #include <map>
#include <stack>
#include <memory> #include <memory>
#include <stack>
#include "flatbuffers/base.h" #include "flatbuffers/base.h"
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
#include "flatbuffers/flexbuffers.h"
#include "flatbuffers/hash.h" #include "flatbuffers/hash.h"
#include "flatbuffers/reflection.h" #include "flatbuffers/reflection.h"
#include "flatbuffers/flexbuffers.h"
#if !defined(FLATBUFFERS_CPP98_STL) #if !defined(FLATBUFFERS_CPP98_STL)
# include <functional> # include <functional>
@@ -39,6 +39,7 @@ namespace flatbuffers {
// The order of these matters for Is*() functions below. // The order of these matters for Is*() functions below.
// Additionally, Parser::ParseType assumes bool..string is a contiguous range // Additionally, Parser::ParseType assumes bool..string is a contiguous range
// of type tokens. // of type tokens.
// clang-format off
#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ #define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
TD(NONE, "", uint8_t, byte, byte, byte, uint8) \ TD(NONE, "", uint8_t, byte, byte, byte, uint8) \
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8) /* begin scalar/int */ \ TD(UTYPE, "", uint8_t, byte, byte, byte, uint8) /* begin scalar/int */ \
@@ -110,13 +111,12 @@ inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG || inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
t == BASE_TYPE_ULONG; } t == BASE_TYPE_ULONG; }
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; } inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
// clang-format on
extern const char *const kTypeNames[]; extern const char *const kTypeNames[];
extern const char kTypeSizes[]; extern const char kTypeSizes[];
inline size_t SizeOf(BaseType t) { inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
return kTypeSizes[t];
}
struct StructDef; struct StructDef;
struct EnumDef; struct EnumDef;
@@ -125,13 +125,12 @@ class Parser;
// Represents any type in the IDL, which is a combination of the BaseType // Represents any type in the IDL, which is a combination of the BaseType
// and additional information for vectors/structs_. // and additional information for vectors/structs_.
struct Type { struct Type {
explicit Type(BaseType _base_type = BASE_TYPE_NONE, explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
StructDef *_sd = nullptr, EnumDef *_ed = nullptr) EnumDef *_ed = nullptr)
: base_type(_base_type), : base_type(_base_type),
element(BASE_TYPE_NONE), element(BASE_TYPE_NONE),
struct_def(_sd), struct_def(_sd),
enum_def(_ed) enum_def(_ed) {}
{}
bool operator==(const Type &o) { bool operator==(const Type &o) {
return base_type == o.base_type && element == o.element && return base_type == o.base_type && element == o.element &&
@@ -151,8 +150,9 @@ struct Type {
// Represents a parsed scalar value, it's type, and field offset. // Represents a parsed scalar value, it's type, and field offset.
struct Value { struct Value {
Value() : constant("0"), offset(static_cast<voffset_t>( Value()
~(static_cast<voffset_t>(0U)))) {} : constant("0"),
offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
Type type; Type type;
std::string constant; std::string constant;
voffset_t offset; voffset_t offset;
@@ -163,9 +163,7 @@ struct Value {
template<typename T> class SymbolTable { template<typename T> class SymbolTable {
public: public:
~SymbolTable() { ~SymbolTable() {
for (auto it = vec.begin(); it != vec.end(); ++it) { for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
delete *it;
}
} }
bool Add(const std::string &name, T *e) { bool Add(const std::string &name, T *e) {
@@ -201,7 +199,6 @@ template<typename T> class SymbolTable {
struct Namespace { struct Namespace {
Namespace() : from_table(0) {} Namespace() : from_table(0) {}
// Given a (potentally unqualified) name, return the "fully qualified" name // Given a (potentally unqualified) name, return the "fully qualified" name
// which has a full namespaced descriptor. // which has a full namespaced descriptor.
// With max_components you can request less than the number of components // With max_components you can request less than the number of components
@@ -215,13 +212,16 @@ struct Namespace {
// Base class for all definition types (fields, structs_, enums_). // Base class for all definition types (fields, structs_, enums_).
struct Definition { struct Definition {
Definition() : generated(false), defined_namespace(nullptr), Definition()
serialized_location(0), index(-1), refcount(1) {} : generated(false),
defined_namespace(nullptr),
serialized_location(0),
index(-1),
refcount(1) {}
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset< flatbuffers::Offset<
reflection::KeyValue>>> flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
SerializeAttributes(FlatBufferBuilder *builder, SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
const Parser &parser) const;
std::string name; std::string name;
std::string file; std::string file;
@@ -237,8 +237,13 @@ struct Definition {
}; };
struct FieldDef : public Definition { struct FieldDef : public Definition {
FieldDef() : deprecated(false), required(false), key(false), FieldDef()
native_inline(false), flexbuffer(false), nested_flatbuffer(NULL), : deprecated(false),
required(false),
key(false),
native_inline(false),
flexbuffer(false),
nested_flatbuffer(NULL),
padding(0) {} padding(0) {}
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id, Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
@@ -263,8 +268,7 @@ struct StructDef : public Definition {
sortbysize(true), sortbysize(true),
has_key(false), has_key(false),
minalign(1), minalign(1),
bytesize(0) bytesize(0) {}
{}
void PadLastField(size_t min_align) { void PadLastField(size_t min_align) {
auto padding = PaddingBytes(bytesize, min_align); auto padding = PaddingBytes(bytesize, min_align);
@@ -300,8 +304,7 @@ inline size_t InlineAlignment(const Type &type) {
} }
struct EnumVal { struct EnumVal {
EnumVal(const std::string &_name, int64_t _val) EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
: name(_name), value(_val) {}
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder) const; Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder) const;
@@ -315,12 +318,10 @@ struct EnumDef : public Definition {
EnumDef() : is_union(false), uses_type_aliases(false) {} EnumDef() : is_union(false), uses_type_aliases(false) {}
EnumVal *ReverseLookup(int enum_idx, bool skip_union_default = true) { EnumVal *ReverseLookup(int enum_idx, bool skip_union_default = true) {
for (auto it = vals.vec.begin() + static_cast<int>(is_union && for (auto it = vals.vec.begin() +
skip_union_default); static_cast<int>(is_union && skip_union_default);
it != vals.vec.end(); ++it) { it != vals.vec.end(); ++it) {
if ((*it)->value == enum_idx) { if ((*it)->value == enum_idx) { return *it; }
return *it;
}
} }
return nullptr; return nullptr;
} }
@@ -338,8 +339,7 @@ inline bool EqualByName(const Type &a, const Type &b) {
return a.base_type == b.base_type && a.element == b.element && return a.base_type == b.base_type && a.element == b.element &&
(a.struct_def == b.struct_def || (a.struct_def == b.struct_def ||
a.struct_def->name == b.struct_def->name) && a.struct_def->name == b.struct_def->name) &&
(a.enum_def == b.enum_def || (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
a.enum_def->name == b.enum_def->name);
} }
struct RPCCall { struct RPCCall {
@@ -419,7 +419,9 @@ struct IDLOptions {
use_goog_js_export_format(false), use_goog_js_export_format(false),
output_default_scalars_in_json(false), output_default_scalars_in_json(false),
indent_step(2), indent_step(2),
output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false), output_enum_identifiers(true),
prefixed_enums(true),
scoped_enums(false),
include_dependence_headers(true), include_dependence_headers(true),
mutable_buffer(false), mutable_buffer(false),
one_file(false), one_file(false),
@@ -481,7 +483,10 @@ class CheckedError {
~CheckedError() { assert(has_been_checked_); } ~CheckedError() { assert(has_been_checked_); }
bool Check() { has_been_checked_ = true; return is_error_; } bool Check() {
has_been_checked_ = true;
return is_error_;
}
private: private:
bool is_error_; bool is_error_;
@@ -490,12 +495,14 @@ class CheckedError {
// Additionally, in GCC we can get these errors statically, for additional // Additionally, in GCC we can get these errors statically, for additional
// assurance: // assurance:
// clang-format off
#ifdef __GNUC__ #ifdef __GNUC__
#define FLATBUFFERS_CHECKED_ERROR CheckedError \ #define FLATBUFFERS_CHECKED_ERROR CheckedError \
__attribute__((warn_unused_result)) __attribute__((warn_unused_result))
#else #else
#define FLATBUFFERS_CHECKED_ERROR CheckedError #define FLATBUFFERS_CHECKED_ERROR CheckedError
#endif #endif
// clang-format on
class Parser : public ParserState { class Parser : public ParserState {
public: public:
@@ -606,6 +613,7 @@ private:
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field, FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn, size_t parent_fieldn,
const StructDef *parent_struct_def); const StructDef *parent_struct_def);
// clang-format off
#if defined(FLATBUFFERS_CPP98_STL) #if defined(FLATBUFFERS_CPP98_STL)
typedef CheckedError (*ParseTableDelimitersBody)( typedef CheckedError (*ParseTableDelimitersBody)(
const std::string &name, size_t &fieldn, const StructDef *struct_def, const std::string &name, size_t &fieldn, const StructDef *struct_def,
@@ -615,6 +623,7 @@ private:
const StructDef*, void*)> const StructDef*, void*)>
ParseTableDelimitersBody; ParseTableDelimitersBody;
#endif // defined(FLATBUFFERS_CPP98_STL) #endif // defined(FLATBUFFERS_CPP98_STL)
// clang-format on
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn, FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
const StructDef *struct_def, const StructDef *struct_def,
ParseTableDelimitersBody body, ParseTableDelimitersBody body,
@@ -623,6 +632,7 @@ private:
std::string *value, uoffset_t *ovalue); std::string *value, uoffset_t *ovalue);
void SerializeStruct(const StructDef &struct_def, const Value &val); void SerializeStruct(const StructDef &struct_def, const Value &val);
void AddVector(bool sortbysize, int count); void AddVector(bool sortbysize, int count);
// clang-format off
#if defined(FLATBUFFERS_CPP98_STL) #if defined(FLATBUFFERS_CPP98_STL)
typedef CheckedError (*ParseVectorDelimitersBody)(size_t &count, typedef CheckedError (*ParseVectorDelimitersBody)(size_t &count,
void *state); void *state);
@@ -630,6 +640,7 @@ private:
typedef std::function<CheckedError(size_t&, void*)> typedef std::function<CheckedError(size_t&, void*)>
ParseVectorDelimitersBody; ParseVectorDelimitersBody;
#endif // defined(FLATBUFFERS_CPP98_STL) #endif // defined(FLATBUFFERS_CPP98_STL)
// clang-format on
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters( FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(
size_t &count, ParseVectorDelimitersBody body, void *state); size_t &count, ParseVectorDelimitersBody body, void *state);
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue); FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);

View File

@@ -65,8 +65,7 @@ struct IterationVisitor {
virtual void EndVector() {} virtual void EndVector() {}
virtual void Element(size_t /*i*/, ElementaryType /*type*/, virtual void Element(size_t /*i*/, ElementaryType /*type*/,
const TypeTable * /*type_table*/, const TypeTable * /*type_table*/,
const uint8_t * /*val*/) const uint8_t * /*val*/) {}
{}
virtual ~IterationVisitor() {} virtual ~IterationVisitor() {}
}; };
@@ -75,34 +74,24 @@ inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
case ET_UTYPE: case ET_UTYPE:
case ET_BOOL: case ET_BOOL:
case ET_CHAR: case ET_CHAR:
case ET_UCHAR: case ET_UCHAR: return 1;
return 1;
case ET_SHORT: case ET_SHORT:
case ET_USHORT: case ET_USHORT: return 2;
return 2;
case ET_INT: case ET_INT:
case ET_UINT: case ET_UINT:
case ET_FLOAT: case ET_FLOAT:
case ET_STRING: case ET_STRING: return 4;
return 4;
case ET_LONG: case ET_LONG:
case ET_ULONG: case ET_ULONG:
case ET_DOUBLE: case ET_DOUBLE: return 8;
return 8;
case ET_SEQUENCE: case ET_SEQUENCE:
switch (type_table->st) { switch (type_table->st) {
case ST_TABLE: case ST_TABLE:
case ST_UNION: case ST_UNION: return 4;
return 4; case ST_STRUCT: return type_table->values[type_table->num_elems];
case ST_STRUCT: default: assert(false); return 1;
return type_table->values[type_table->num_elems];
default:
assert(false);
return 1;
} }
default: default: assert(false); return 1;
assert(false);
return 1;
} }
} }
@@ -129,10 +118,8 @@ void IterateObject(const uint8_t *obj, const TypeTable *type_table,
IterationVisitor *visitor); IterationVisitor *visitor);
inline void IterateValue(ElementaryType type, const uint8_t *val, inline void IterateValue(ElementaryType type, const uint8_t *val,
const TypeTable *type_table, const TypeTable *type_table, const uint8_t *prev_val,
const uint8_t *prev_val, soffset_t vector_index, IterationVisitor *visitor) {
soffset_t vector_index,
IterationVisitor *visitor) {
switch (type) { switch (type) {
case ET_UTYPE: { case ET_UTYPE: {
auto tval = *reinterpret_cast<const uint8_t *>(val); auto tval = *reinterpret_cast<const uint8_t *>(val);
@@ -200,9 +187,7 @@ inline void IterateValue(ElementaryType type, const uint8_t *val,
val += ReadScalar<uoffset_t>(val); val += ReadScalar<uoffset_t>(val);
IterateObject(val, type_table, visitor); IterateObject(val, type_table, visitor);
break; break;
case ST_STRUCT: case ST_STRUCT: IterateObject(val, type_table, visitor); break;
IterateObject(val, type_table, visitor);
break;
case ST_UNION: { case ST_UNION: {
val += ReadScalar<uoffset_t>(val); val += ReadScalar<uoffset_t>(val);
assert(prev_val); assert(prev_val);
@@ -211,10 +196,10 @@ inline void IterateValue(ElementaryType type, const uint8_t *val,
auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val); auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
union_type = type_vec->Get(static_cast<uoffset_t>(vector_index)); union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
} }
auto type_code_idx = LookupEnum(union_type, type_table->values, auto type_code_idx =
type_table->num_elems); LookupEnum(union_type, type_table->values, type_table->num_elems);
if (type_code_idx >= 0 && type_code_idx < if (type_code_idx >= 0 &&
static_cast<int32_t>(type_table->num_elems)) { type_code_idx < static_cast<int32_t>(type_table->num_elems)) {
auto type_code = type_table->type_codes[type_code_idx]; auto type_code = type_table->type_codes[type_code_idx];
switch (type_code.base_type) { switch (type_code.base_type) {
case ET_SEQUENCE: { case ET_SEQUENCE: {
@@ -225,17 +210,14 @@ inline void IterateValue(ElementaryType type, const uint8_t *val,
case ET_STRING: case ET_STRING:
visitor->String(reinterpret_cast<const String *>(val)); visitor->String(reinterpret_cast<const String *>(val));
break; break;
default: default: visitor->Unknown(val);
visitor->Unknown(val);
} }
} else { } else {
visitor->Unknown(val); visitor->Unknown(val);
} }
break; break;
} }
case ST_ENUM: case ST_ENUM: assert(false); break;
assert(false);
break;
} }
break; break;
} }
@@ -257,9 +239,7 @@ inline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
auto is_vector = type_code.is_vector != 0; auto is_vector = type_code.is_vector != 0;
auto ref_idx = type_code.sequence_ref; auto ref_idx = type_code.sequence_ref;
const TypeTable *ref = nullptr; const TypeTable *ref = nullptr;
if (ref_idx >= 0) { if (ref_idx >= 0) { ref = type_table->type_refs[ref_idx](); }
ref = type_table->type_refs[ref_idx]();
}
auto name = type_table->names ? type_table->names[i] : nullptr; auto name = type_table->names ? type_table->names[i] : nullptr;
const uint8_t *val = nullptr; const uint8_t *val = nullptr;
if (type_table->st == ST_TABLE) { if (type_table->st == ST_TABLE) {
@@ -310,11 +290,16 @@ struct ToStringVisitor : public IterationVisitor {
const char *name, const uint8_t *val) { const char *name, const uint8_t *val) {
if (!val) return; if (!val) return;
if (set_idx) s += ", "; if (set_idx) s += ", ";
if (name) { s += name; s += ": "; } if (name) {
s += name;
s += ": ";
}
} }
template<typename T> void Named(T x, const char *name) { template<typename T> void Named(T x, const char *name) {
if (name) s+= name; if (name)
else s+= NumToString(x); s += name;
else
s += NumToString(x);
} }
void UType(uint8_t x, const char *name) { Named(x, name); } void UType(uint8_t x, const char *name) { Named(x, name); }
void Bool(bool x) { s += x ? "true" : "false"; } void Bool(bool x) { s += x ? "true" : "false"; }

View File

@@ -30,14 +30,18 @@ namespace flatbuffers {
// ------------------------- GETTERS ------------------------- // ------------------------- GETTERS -------------------------
inline bool IsScalar (reflection::BaseType t) { return t >= reflection::UType && inline bool IsScalar(reflection::BaseType t) {
t <= reflection::Double; } return t >= reflection::UType && t <= reflection::Double;
inline bool IsInteger(reflection::BaseType t) { return t >= reflection::UType && }
t <= reflection::ULong; } inline bool IsInteger(reflection::BaseType t) {
inline bool IsFloat (reflection::BaseType t) { return t == reflection::Float || return t >= reflection::UType && t <= reflection::ULong;
t == reflection::Double; } }
inline bool IsLong (reflection::BaseType t) { return t == reflection::Long || inline bool IsFloat(reflection::BaseType t) {
t == reflection::ULong; } return t == reflection::Float || t == reflection::Double;
}
inline bool IsLong(reflection::BaseType t) {
return t == reflection::Long || t == reflection::ULong;
}
// Size of a basic type, don't use with structs. // Size of a basic type, don't use with structs.
inline size_t GetTypeSize(reflection::BaseType base_type) { inline size_t GetTypeSize(reflection::BaseType base_type) {
@@ -48,8 +52,7 @@ inline size_t GetTypeSize(reflection::BaseType base_type) {
// Same as above, but now correctly returns the size of a struct if // Same as above, but now correctly returns the size of a struct if
// the field (or vector element) is a struct. // the field (or vector element) is a struct.
inline size_t GetTypeSizeInline(reflection::BaseType base_type, inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
int type_index,
const reflection::Schema &schema) { const reflection::Schema &schema) {
if (base_type == reflection::Obj && if (base_type == reflection::Obj &&
schema.objects()->Get(type_index)->is_struct()) { schema.objects()->Get(type_index)->is_struct()) {
@@ -80,16 +83,16 @@ template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
} }
// Get a field, if you know it's an integer, and its exact type. // Get a field, if you know it's an integer, and its exact type.
template<typename T> T GetFieldI(const Table &table, template<typename T>
const reflection::Field &field) { T GetFieldI(const Table &table, const reflection::Field &field) {
assert(sizeof(T) == GetTypeSize(field.type()->base_type())); assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
return table.GetField<T>(field.offset(), return table.GetField<T>(field.offset(),
static_cast<T>(field.default_integer())); static_cast<T>(field.default_integer()));
} }
// Get a field, if you know it's floating point and its exact type. // Get a field, if you know it's floating point and its exact type.
template<typename T> T GetFieldF(const Table &table, template<typename T>
const reflection::Field &field) { T GetFieldF(const Table &table, const reflection::Field &field) {
assert(sizeof(T) == GetTypeSize(field.type()->base_type())); assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
return table.GetField<T>(field.offset(), return table.GetField<T>(field.offset(),
static_cast<T>(field.default_real())); static_cast<T>(field.default_real()));
@@ -103,8 +106,8 @@ inline const String *GetFieldS(const Table &table,
} }
// Get a field, if you know it's a vector. // Get a field, if you know it's a vector.
template<typename T> Vector<T> *GetFieldV(const Table &table, template<typename T>
const reflection::Field &field) { Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) {
assert(field.type()->base_type() == reflection::Vector && assert(field.type()->base_type() == reflection::Vector &&
sizeof(T) == GetTypeSize(field.type()->element())); sizeof(T) == GetTypeSize(field.type()->element()));
return table.GetPointer<Vector<T> *>(field.offset()); return table.GetPointer<Vector<T> *>(field.offset());
@@ -119,8 +122,7 @@ inline VectorOfAny *GetFieldAnyV(const Table &table,
} }
// Get a field, if you know it's a table. // Get a field, if you know it's a table.
inline Table *GetFieldT(const Table &table, inline Table *GetFieldT(const Table &table, const reflection::Field &field) {
const reflection::Field &field) {
assert(field.type()->base_type() == reflection::Obj || assert(field.type()->base_type() == reflection::Obj ||
field.type()->base_type() == reflection::Union); field.type()->base_type() == reflection::Union);
return table.GetPointer<Table *>(field.offset()); return table.GetPointer<Table *>(field.offset());
@@ -153,8 +155,7 @@ double GetAnyValueF(reflection::BaseType type, const uint8_t *data);
// All scalars converted using stringstream, strings as-is, and all other // All scalars converted using stringstream, strings as-is, and all other
// data types provide some level of debug-pretty-printing. // data types provide some level of debug-pretty-printing.
std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data, std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
const reflection::Schema *schema, const reflection::Schema *schema, int type_index);
int type_index);
// Get any table field as a 64bit int, regardless of what type it is. // Get any table field as a 64bit int, regardless of what type it is.
inline int64_t GetAnyFieldI(const Table &table, inline int64_t GetAnyFieldI(const Table &table,
@@ -165,14 +166,12 @@ inline int64_t GetAnyFieldI(const Table &table,
} }
// Get any table field as a double, regardless of what type it is. // Get any table field as a double, regardless of what type it is.
inline double GetAnyFieldF(const Table &table, inline double GetAnyFieldF(const Table &table, const reflection::Field &field) {
const reflection::Field &field) {
auto field_ptr = table.GetAddressOf(field.offset()); auto field_ptr = table.GetAddressOf(field.offset());
return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr) return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
: field.default_real(); : field.default_real();
} }
// Get any table field as a string, regardless of what type it is. // Get any table field as a string, regardless of what type it is.
// You may pass nullptr for the schema if you don't care to have fields that // You may pass nullptr for the schema if you don't care to have fields that
// are of table type pretty-printed. // are of table type pretty-printed.
@@ -186,15 +185,13 @@ inline std::string GetAnyFieldS(const Table &table,
} }
// Get any struct field as a 64bit int, regardless of what type it is. // Get any struct field as a 64bit int, regardless of what type it is.
inline int64_t GetAnyFieldI(const Struct &st, inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field) {
const reflection::Field &field) {
return GetAnyValueI(field.type()->base_type(), return GetAnyValueI(field.type()->base_type(),
st.GetAddressOf(field.offset())); st.GetAddressOf(field.offset()));
} }
// Get any struct field as a double, regardless of what type it is. // Get any struct field as a double, regardless of what type it is.
inline double GetAnyFieldF(const Struct &st, inline double GetAnyFieldF(const Struct &st, const reflection::Field &field) {
const reflection::Field &field) {
return GetAnyValueF(field.type()->base_type(), return GetAnyValueF(field.type()->base_type(),
st.GetAddressOf(field.offset())); st.GetAddressOf(field.offset()));
} }
@@ -228,8 +225,8 @@ inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
// Get a vector element that's a table/string/vector from a generic vector. // Get a vector element that's a table/string/vector from a generic vector.
// Pass Table/String/VectorOfAny as template parameter. // Pass Table/String/VectorOfAny as template parameter.
// Warning: does no typechecking. // Warning: does no typechecking.
template<typename T> T *GetAnyVectorElemPointer(const VectorOfAny *vec, template<typename T>
size_t i) { T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i; auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
return (T *)(elem_ptr + ReadScalar<uoffset_t>(elem_ptr)); return (T *)(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
} }
@@ -239,34 +236,32 @@ template<typename T> T *GetAnyVectorElemPointer(const VectorOfAny *vec,
// Get elem_size from GetTypeSizeInline(). // Get elem_size from GetTypeSizeInline().
// Note: little-endian data on all platforms, use EndianScalar() instead of // Note: little-endian data on all platforms, use EndianScalar() instead of
// raw pointer access with scalars). // raw pointer access with scalars).
template<typename T> T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, template<typename T>
size_t i, T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i,
size_t elem_size) { size_t elem_size) {
// C-cast to allow const conversion. // C-cast to allow const conversion.
return (T *)(vec->Data() + elem_size * i); return (T *)(vec->Data() + elem_size * i);
} }
// Similarly, for elements of tables. // Similarly, for elements of tables.
template<typename T> T *GetAnyFieldAddressOf(const Table &table, template<typename T>
const reflection::Field &field) { T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) {
return (T *)table.GetAddressOf(field.offset()); return (T *)table.GetAddressOf(field.offset());
} }
// Similarly, for elements of structs. // Similarly, for elements of structs.
template<typename T> T *GetAnyFieldAddressOf(const Struct &st, template<typename T>
const reflection::Field &field) { T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
return (T *)st.GetAddressOf(field.offset()); return (T *)st.GetAddressOf(field.offset());
} }
// ------------------------- SETTERS ------------------------- // ------------------------- SETTERS -------------------------
// Set any scalar field, if you know its exact type. // Set any scalar field, if you know its exact type.
template<typename T> bool SetField(Table *table, const reflection::Field &field, template<typename T>
T val) { bool SetField(Table *table, const reflection::Field &field, T val) {
reflection::BaseType type = field.type()->base_type(); reflection::BaseType type = field.type()->base_type();
if (!IsScalar(type)) { if (!IsScalar(type)) { return false; }
return false;
}
assert(sizeof(T) == GetTypeSize(type)); assert(sizeof(T) == GetTypeSize(type));
T def; T def;
if (IsInteger(type)) { if (IsInteger(type)) {
@@ -352,7 +347,6 @@ inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val); SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
} }
// ------------------------- RESIZING SETTERS ------------------------- // ------------------------- RESIZING SETTERS -------------------------
// "smart" pointer for use with resizing vectors: turns a pointer inside // "smart" pointer for use with resizing vectors: turns a pointer inside
@@ -366,21 +360,19 @@ template<typename T, typename U> class pointer_inside_vector {
T *operator*() const { T *operator*() const {
return reinterpret_cast<T *>( return reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>( reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) + offset_);
flatbuffers::vector_data(vec_)) + offset_);
}
T *operator->() const {
return operator*();
} }
T *operator->() const { return operator*(); }
void operator=(const pointer_inside_vector &piv); void operator=(const pointer_inside_vector &piv);
private: private:
size_t offset_; size_t offset_;
std::vector<U> &vec_; std::vector<U> &vec_;
}; };
// Helper to create the above easily without specifying template args. // Helper to create the above easily without specifying template args.
template<typename T, typename U> pointer_inside_vector<T, U> piv(T *ptr, template<typename T, typename U>
std::vector<U> &vec) { pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec) {
return pointer_inside_vector<T, U>(ptr, vec); return pointer_inside_vector<T, U>(ptr, vec);
} }
@@ -424,11 +416,9 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
const Vector<T> *vec, std::vector<uint8_t> *flatbuf, const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr) { const reflection::Object *root_table = nullptr) {
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size()); auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
auto newelems = ResizeAnyVector(schema, newsize, auto newelems = ResizeAnyVector(
reinterpret_cast<const VectorOfAny *>(vec), schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(),
vec->size(), static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table);
static_cast<uoffset_t>(sizeof(T)), flatbuf,
root_table);
// Set new elements to "val". // Set new elements to "val".
for (int i = 0; i < delta_elem; i++) { for (int i = 0; i < delta_elem; i++) {
auto loc = newelems + i * sizeof(T); auto loc = newelems + i * sizeof(T);
@@ -479,10 +469,8 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
// root should point to the root type for this flatbuffer. // root should point to the root type for this flatbuffer.
// buf should point to the start of flatbuffer data. // buf should point to the start of flatbuffer data.
// length specifies the size of the flatbuffer data. // length specifies the size of the flatbuffer data.
bool Verify(const reflection::Schema &schema, bool Verify(const reflection::Schema &schema, const reflection::Object &root,
const reflection::Object &root, const uint8_t *buf, size_t length);
const uint8_t *buf,
size_t length);
} // namespace flatbuffers } // namespace flatbuffers

View File

@@ -37,17 +37,15 @@ class Registry {
// Generate text from an arbitrary FlatBuffer by looking up its // Generate text from an arbitrary FlatBuffer by looking up its
// file_identifier in the registry. // file_identifier in the registry.
bool FlatBufferToText(const uint8_t *flatbuf, size_t len, bool FlatBufferToText(const uint8_t *flatbuf, size_t len, std::string *dest) {
std::string *dest) {
// Get the identifier out of the buffer. // Get the identifier out of the buffer.
// If the buffer is truncated, exit. // If the buffer is truncated, exit.
if (len < sizeof(uoffset_t) + if (len < sizeof(uoffset_t) + FlatBufferBuilder::kFileIdentifierLength) {
FlatBufferBuilder::kFileIdentifierLength) {
lasterror_ = "buffer truncated"; lasterror_ = "buffer truncated";
return false; return false;
} }
std::string ident(reinterpret_cast<const char *>(flatbuf) + std::string ident(
sizeof(uoffset_t), reinterpret_cast<const char *>(flatbuf) + sizeof(uoffset_t),
FlatBufferBuilder::kFileIdentifierLength); FlatBufferBuilder::kFileIdentifierLength);
// Load and parse the schema. // Load and parse the schema.
Parser parser; Parser parser;
@@ -82,9 +80,7 @@ class Registry {
// If schemas used contain include statements, call this function for every // If schemas used contain include statements, call this function for every
// directory the parser should search them for. // directory the parser should search them for.
void AddIncludeDirectory(const char *path) { void AddIncludeDirectory(const char *path) { include_paths_.push_back(path); }
include_paths_.push_back(path);
}
// Returns a human readable error if any of the above functions fail. // Returns a human readable error if any of the above functions fail.
const std::string &GetLastError() { return lasterror_; } const std::string &GetLastError() { return lasterror_; }

View File

@@ -17,6 +17,8 @@
#ifndef FLATBUFFERS_STL_EMULATION_H_ #ifndef FLATBUFFERS_STL_EMULATION_H_
#define FLATBUFFERS_STL_EMULATION_H_ #define FLATBUFFERS_STL_EMULATION_H_
// clang-format off
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>

View File

@@ -17,13 +17,13 @@
#ifndef FLATBUFFERS_UTIL_H_ #ifndef FLATBUFFERS_UTIL_H_
#define FLATBUFFERS_UTIL_H_ #define FLATBUFFERS_UTIL_H_
#include <fstream> #include <assert.h>
#include <iomanip>
#include <string>
#include <sstream>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#ifdef _WIN32 #ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN # ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
@@ -31,18 +31,17 @@
# ifndef NOMINMAX # ifndef NOMINMAX
# define NOMINMAX # define NOMINMAX
# endif # endif
#include <windows.h>
#include <winbase.h>
# include <direct.h> # include <direct.h>
# include <winbase.h>
# include <windows.h>
#else #else
# include <limits.h> # include <limits.h>
#endif #endif
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#include "flatbuffers/base.h" #include "flatbuffers/base.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.
@@ -67,8 +66,8 @@ template<> inline std::string NumToString<unsigned char>(unsigned char t) {
return std::string(buf); return std::string(buf);
} }
template <> inline std::string NumToString<unsigned long long>( template<>
unsigned long long t) { inline std::string NumToString<unsigned long long>(unsigned long long t) {
char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1 char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1
snprintf(buf, sizeof(buf), "%llu", t); snprintf(buf, sizeof(buf), "%llu", t);
return std::string(buf); return std::string(buf);
@@ -100,10 +99,7 @@ template<> inline std::string NumToString<float>(float t) {
// For example, IntToStringHex(0x23, 8) returns the string "00000023". // For example, IntToStringHex(0x23, 8) returns the string "00000023".
inline std::string IntToStringHex(int i, int xdigits) { inline std::string IntToStringHex(int i, int xdigits) {
std::stringstream ss; std::stringstream ss;
ss << std::setw(xdigits) ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
<< std::setfill('0')
<< std::hex
<< std::uppercase
<< i; << i;
return ss.str(); return ss.str();
} }
@@ -111,21 +107,25 @@ inline std::string IntToStringHex(int i, int xdigits) {
// Portable implementation of strtoll(). // Portable implementation of strtoll().
inline int64_t StringToInt(const char *str, char **endptr = nullptr, inline int64_t StringToInt(const char *str, char **endptr = nullptr,
int base = 10) { int base = 10) {
// clang-format off
#ifdef _MSC_VER #ifdef _MSC_VER
return _strtoi64(str, endptr, base); return _strtoi64(str, endptr, base);
#else #else
return strtoll(str, endptr, base); return strtoll(str, endptr, base);
#endif #endif
// clang-format on
} }
// Portable implementation of strtoull(). // Portable implementation of strtoull().
inline uint64_t StringToUInt(const char *str, char **endptr = nullptr, inline uint64_t StringToUInt(const char *str, char **endptr = nullptr,
int base = 10) { int base = 10) {
// clang-format off
#ifdef _MSC_VER #ifdef _MSC_VER
return _strtoui64(str, endptr, base); return _strtoui64(str, endptr, base);
#else #else
return strtoull(str, endptr, base); return strtoull(str, endptr, base);
#endif #endif
// clang-format on
} }
typedef bool (*LoadFileFunction)(const char *filename, bool binary, typedef bool (*LoadFileFunction)(const char *filename, bool binary,
@@ -134,9 +134,8 @@ typedef bool (*FileExistsFunction)(const char *filename);
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function); LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
FileExistsFunction SetFileExistsFunction(FileExistsFunction FileExistsFunction SetFileExistsFunction(
file_exists_function); FileExistsFunction file_exists_function);
// Check if file "name" exists. // Check if file "name" exists.
bool FileExists(const char *name); bool FileExists(const char *name);
@@ -239,16 +238,19 @@ inline std::string PosixPath(const char *path) {
inline void EnsureDirExists(const std::string &filepath) { inline void EnsureDirExists(const std::string &filepath) {
auto parent = StripFileName(filepath); auto parent = StripFileName(filepath);
if (parent.length()) EnsureDirExists(parent); if (parent.length()) EnsureDirExists(parent);
// clang-format off
#ifdef _WIN32 #ifdef _WIN32
(void)_mkdir(filepath.c_str()); (void)_mkdir(filepath.c_str());
#else #else
mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP); mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
#endif #endif
// clang-format on
} }
// Obtains the absolute path from any other path. // Obtains the absolute path from any other path.
// Returns the input path if the absolute path couldn't be resolved. // Returns the input path if the absolute path couldn't be resolved.
inline std::string AbsolutePath(const std::string &filepath) { inline std::string AbsolutePath(const std::string &filepath) {
// clang-format off
#ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION #ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
return filepath; return filepath;
#else #else
@@ -262,6 +264,7 @@ inline std::string AbsolutePath(const std::string &filepath) {
? abs_path ? abs_path
: filepath; : filepath;
#endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION #endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
// clang-format on
} }
// To and from UTF-8 unicode conversion functions // To and from UTF-8 unicode conversion functions
@@ -309,9 +312,7 @@ inline int FromUTF8(const char **in) {
if ((**in << len) & 0x80) return -1; // Bit after leading 1's must be 0. if ((**in << len) & 0x80) return -1; // Bit after leading 1's must be 0.
if (!len) return *(*in)++; if (!len) return *(*in)++;
// UTF-8 encoded values with a length are between 2 and 4 bytes. // UTF-8 encoded values with a length are between 2 and 4 bytes.
if (len < 2 || len > 4) { if (len < 2 || len > 4) { return -1; }
return -1;
}
// Grab initial bits of the code. // Grab initial bits of the code.
int ucc = *(*in)++ & ((1 << (7 - len)) - 1); int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
for (int i = 0; i < len - 1; i++) { for (int i = 0; i < len - 1; i++) {
@@ -321,28 +322,20 @@ inline int FromUTF8(const char **in) {
} }
// UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for // UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
// UTF-16 surrogate pairs). // UTF-16 surrogate pairs).
if (ucc >= 0xD800 && ucc <= 0xDFFF) { if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; }
return -1;
}
// UTF-8 must represent code points in their shortest possible encoding. // UTF-8 must represent code points in their shortest possible encoding.
switch (len) { switch (len) {
case 2: case 2:
// Two bytes of UTF-8 can represent code points from U+0080 to U+07FF. // Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
if (ucc < 0x0080 || ucc > 0x07FF) { if (ucc < 0x0080 || ucc > 0x07FF) { return -1; }
return -1;
}
break; break;
case 3: case 3:
// Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF. // Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
if (ucc < 0x0800 || ucc > 0xFFFF) { if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; }
return -1;
}
break; break;
case 4: case 4:
// Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF. // Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
if (ucc < 0x10000 || ucc > 0x10FFFF) { if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; }
return -1;
}
break; break;
} }
return ucc; return ucc;
@@ -421,7 +414,8 @@ inline bool EscapeString(const char *s, size_t length, std::string *_text,
text += "\\u"; text += "\\u";
text += IntToStringHex(ucc, 4); text += IntToStringHex(ucc, 4);
} else if (ucc <= 0x10FFFF) { } else if (ucc <= 0x10FFFF) {
// Encode Unicode SMP values to a surrogate pair using two \u escapes. // Encode Unicode SMP values to a surrogate pair using two \u
// escapes.
uint32_t base = ucc - 0x10000; uint32_t base = ucc - 0x10000;
auto high_surrogate = (base >> 10) + 0xD800; auto high_surrogate = (base >> 10) + 0xD800;
auto low_surrogate = (base & 0x03FF) + 0xDC00; auto low_surrogate = (base & 0x03FF) + 0xDC00;

View File

@@ -102,4 +102,3 @@ int main(int /*argc*/, const char * /*argv*/[]) {
printf("The FlatBuffer was successfully created and verified!\n"); printf("The FlatBuffer was successfully created and verified!\n");
} }

2
src/clang-format.sh Normal file
View File

@@ -0,0 +1,2 @@
clang-format -i -style=file include/flatbuffers/* src/*.cpp tests/test.cpp samples/*.cpp grpc/src/compiler/schema_interface.h grpc/tests/*.cpp
git checkout include/flatbuffers/reflection_generated.h

View File

@@ -27,17 +27,12 @@
namespace flatbuffers { namespace flatbuffers {
void CodeWriter::operator+=(std::string text) { void CodeWriter::operator+=(std::string text) {
while (true) { while (true) {
auto begin = text.find("{{"); auto begin = text.find("{{");
if (begin == std::string::npos) { if (begin == std::string::npos) { break; }
break;
}
auto end = text.find("}}"); auto end = text.find("}}");
if (end == std::string::npos || end < begin) { if (end == std::string::npos || end < begin) { break; }
break;
}
// Write all the text before the first {{ into the stream. // Write all the text before the first {{ into the stream.
stream_.write(text.c_str(), begin); stream_.write(text.c_str(), begin);
@@ -119,7 +114,6 @@ std::string BaseGenerator::WrapInNameSpace(const Namespace *ns,
return qualified_name + name; return qualified_name + name;
} }
std::string BaseGenerator::WrapInNameSpace(const Definition &def) const { std::string BaseGenerator::WrapInNameSpace(const Definition &def) const {
return WrapInNameSpace(def.defined_namespace, def.name); return WrapInNameSpace(def.defined_namespace, def.name);
} }
@@ -150,12 +144,12 @@ void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
if (config != nullptr && config->first_line != nullptr) { if (config != nullptr && config->first_line != nullptr) {
code += std::string(prefix) + std::string(config->first_line) + "\n"; code += std::string(prefix) + std::string(config->first_line) + "\n";
} }
std::string line_prefix = std::string(prefix) + std::string line_prefix =
((config != nullptr && config->content_line_prefix != nullptr) ? std::string(prefix) +
config->content_line_prefix : "///"); ((config != nullptr && config->content_line_prefix != nullptr)
for (auto it = dc.begin(); ? config->content_line_prefix
it != dc.end(); : "///");
++it) { for (auto it = dc.begin(); it != dc.end(); ++it) {
code += line_prefix + *it + "\n"; code += line_prefix + *it + "\n";
} }
if (config != nullptr && config->last_line != nullptr) { if (config != nullptr && config->last_line != nullptr) {

View File

@@ -20,12 +20,10 @@
#define FLATC_VERSION "1.8.0 (" __DATE__ " " __TIME__ ")" #define FLATC_VERSION "1.8.0 (" __DATE__ " " __TIME__ ")"
namespace flatbuffers { namespace flatbuffers {
void FlatCompiler::ParseFile( void FlatCompiler::ParseFile(
flatbuffers::Parser &parser, flatbuffers::Parser &parser, const std::string &filename,
const std::string &filename,
const std::string &contents, const std::string &contents,
std::vector<const char *> &include_directories) const { std::vector<const char *> &include_directories) const {
auto local_include_directory = flatbuffers::StripFileName(filename); auto local_include_directory = flatbuffers::StripFileName(filename);
@@ -60,6 +58,7 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
ss << " " << full_name.str() << " " << name << " " << help << ".\n"; ss << " " << full_name.str() << " " << name << " " << help << ".\n";
} }
// clang-format off
ss << ss <<
" -o PATH Prefix PATH to all generated files.\n" " -o PATH Prefix PATH to all generated files.\n"
" -I PATH Search for includes in the specified path.\n" " -I PATH Search for includes in the specified path.\n"
@@ -121,6 +120,7 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
"Output files are named using the base file name of the input,\n" "Output files are named using the base file name of the input,\n"
"and written to the current directory or the path given by -o.\n" "and written to the current directory or the path given by -o.\n"
"example: " << program_name << " -c -b schema1.fbs schema2.fbs data.json\n"; "example: " << program_name << " -c -b schema1.fbs schema2.fbs data.json\n";
// clang-format on
return ss.str(); return ss.str();
} }
@@ -294,16 +294,15 @@ int FlatCompiler::Compile(int argc, const char** argv) {
std::unique_ptr<flatbuffers::Parser> parser(new flatbuffers::Parser(opts)); std::unique_ptr<flatbuffers::Parser> parser(new flatbuffers::Parser(opts));
for (auto file_it = filenames.begin(); for (auto file_it = filenames.begin(); file_it != filenames.end();
file_it != filenames.end();
++file_it) { ++file_it) {
auto &filename = *file_it; auto &filename = *file_it;
std::string contents; std::string contents;
if (!flatbuffers::LoadFile(filename.c_str(), true, &contents)) if (!flatbuffers::LoadFile(filename.c_str(), true, &contents))
Error("unable to load file: " + filename); Error("unable to load file: " + filename);
bool is_binary = static_cast<size_t>(file_it - filenames.begin()) >= bool is_binary =
binary_files_from; static_cast<size_t>(file_it - filenames.begin()) >= binary_files_from;
auto ext = flatbuffers::GetExtension(filename); auto ext = flatbuffers::GetExtension(filename);
auto is_schema = ext == "fbs" || ext == "proto"; auto is_schema = ext == "fbs" || ext == "proto";
if (is_binary) { if (is_binary) {
@@ -322,10 +321,9 @@ int FlatCompiler::Compile(int argc, const char** argv) {
filename + filename +
"\" matches the schema, use --raw-binary to read this file" "\" matches the schema, use --raw-binary to read this file"
" anyway."); " anyway.");
} else if (!flatbuffers::BufferHasIdentifier(contents.c_str(), } else if (!flatbuffers::BufferHasIdentifier(
parser->file_identifier_.c_str())) { contents.c_str(), parser->file_identifier_.c_str())) {
Error("binary \"" + Error("binary \"" + filename +
filename +
"\" does not have expected file_identifier \"" + "\" does not have expected file_identifier \"" +
parser->file_identifier_ + parser->file_identifier_ +
"\", use --raw-binary to read this file anyway."); "\", use --raw-binary to read this file anyway.");
@@ -346,8 +344,9 @@ int FlatCompiler::Compile(int argc, const char** argv) {
if (!is_schema && !parser->builder_.GetSize()) { if (!is_schema && !parser->builder_.GetSize()) {
// If a file doesn't end in .fbs, it must be json/binary. Ensure we // If a file doesn't end in .fbs, it must be json/binary. Ensure we
// didn't just parse a schema with a different extension. // didn't just parse a schema with a different extension.
Error("input file is neither json nor a .fbs (schema) file: " + Error(
filename, true); "input file is neither json nor a .fbs (schema) file: " + filename,
true);
} }
if (is_schema && !conform_to_schema.empty()) { if (is_schema && !conform_to_schema.empty()) {
auto err = parser->ConformTo(conform_parser); auto err = parser->ConformTo(conform_parser);
@@ -359,8 +358,8 @@ int FlatCompiler::Compile(int argc, const char** argv) {
} }
} }
std::string filebase = flatbuffers::StripPath( std::string filebase =
flatbuffers::StripExtension(filename)); flatbuffers::StripPath(flatbuffers::StripExtension(filename));
for (size_t i = 0; i < params_.num_generators; ++i) { for (size_t i = 0; i < params_.num_generators; ++i) {
parser->opts.lang = params_.generators[i].lang; parser->opts.lang = params_.generators[i].lang;
@@ -368,18 +367,17 @@ int FlatCompiler::Compile(int argc, const char** argv) {
if (!print_make_rules) { if (!print_make_rules) {
flatbuffers::EnsureDirExists(output_path); flatbuffers::EnsureDirExists(output_path);
if ((!params_.generators[i].schema_only || is_schema) && if ((!params_.generators[i].schema_only || is_schema) &&
!params_.generators[i].generate(*parser.get(), output_path, filebase)) { !params_.generators[i].generate(*parser.get(), output_path,
filebase)) {
Error(std::string("Unable to generate ") + Error(std::string("Unable to generate ") +
params_.generators[i].lang_name + params_.generators[i].lang_name + " for " + filebase);
" for " +
filebase);
} }
} else { } else {
std::string make_rule = params_.generators[i].make_rule( std::string make_rule = params_.generators[i].make_rule(
*parser.get(), output_path, filename); *parser.get(), output_path, filename);
if (!make_rule.empty()) if (!make_rule.empty())
printf("%s\n", flatbuffers::WordWrap( printf("%s\n",
make_rule, 80, " ", " \\").c_str()); flatbuffers::WordWrap(make_rule, 80, " ", " \\").c_str());
} }
if (grpc_enabled) { if (grpc_enabled) {
if (params_.generators[i].generateGRPC != nullptr) { if (params_.generators[i].generateGRPC != nullptr) {
@@ -389,8 +387,8 @@ int FlatCompiler::Compile(int argc, const char** argv) {
params_.generators[i].lang_name); params_.generators[i].lang_name);
} }
} else { } else {
Warn(std::string("GRPC interface generator not implemented for ") Warn(std::string("GRPC interface generator not implemented for ") +
+ params_.generators[i].lang_name); params_.generators[i].lang_name);
} }
} }
} }

View File

@@ -19,26 +19,17 @@
static const char *g_program_name = nullptr; static const char *g_program_name = nullptr;
static void Warn(const flatbuffers::FlatCompiler *flatc, static void Warn(const flatbuffers::FlatCompiler *flatc,
const std::string &warn, const std::string &warn, bool show_exe_name) {
bool show_exe_name) {
(void)flatc; (void)flatc;
if (show_exe_name) { if (show_exe_name) { printf("%s: ", g_program_name); }
printf("%s: ", g_program_name);
}
printf("warning: %s\n", warn.c_str()); printf("warning: %s\n", warn.c_str());
} }
static void Error(const flatbuffers::FlatCompiler *flatc, static void Error(const flatbuffers::FlatCompiler *flatc,
const std::string &err, const std::string &err, bool usage, bool show_exe_name) {
bool usage, if (show_exe_name) { printf("%s: ", g_program_name); }
bool show_exe_name) {
if (show_exe_name) {
printf("%s: ", g_program_name);
}
printf("error: %s\n", err.c_str()); printf("error: %s\n", err.c_str());
if (usage) { if (usage) { printf("%s", flatc->GetUsageString(g_program_name).c_str()); }
printf("%s", flatc->GetUsageString(g_program_name).c_str());
}
exit(1); exit(1);
} }
@@ -46,61 +37,43 @@ int main(int argc, const char *argv[]) {
g_program_name = argv[0]; g_program_name = argv[0];
const flatbuffers::FlatCompiler::Generator generators[] = { const flatbuffers::FlatCompiler::Generator generators[] = {
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary", false, { flatbuffers::GenerateBinary, "-b", "--binary", "binary", false, nullptr,
nullptr,
flatbuffers::IDLOptions::kBinary, flatbuffers::IDLOptions::kBinary,
"Generate wire format binaries for any data definitions", "Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule }, flatbuffers::BinaryMakeRule },
{ flatbuffers::GenerateTextFile, "-t", "--json", "text", false, { flatbuffers::GenerateTextFile, "-t", "--json", "text", false, nullptr,
nullptr,
flatbuffers::IDLOptions::kJson, flatbuffers::IDLOptions::kJson,
"Generate text output for any data definitions", "Generate text output for any data definitions",
flatbuffers::TextMakeRule }, flatbuffers::TextMakeRule },
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++", true, { flatbuffers::GenerateCPP, "-c", "--cpp", "C++", true,
flatbuffers::GenerateCppGRPC, flatbuffers::GenerateCppGRPC, flatbuffers::IDLOptions::kCpp,
flatbuffers::IDLOptions::kCpp, "Generate C++ headers for tables/structs", flatbuffers::CPPMakeRule },
"Generate C++ headers for tables/structs",
flatbuffers::CPPMakeRule },
{ flatbuffers::GenerateGo, "-g", "--go", "Go", true, { flatbuffers::GenerateGo, "-g", "--go", "Go", true,
flatbuffers::GenerateGoGRPC, flatbuffers::GenerateGoGRPC, flatbuffers::IDLOptions::kGo,
flatbuffers::IDLOptions::kGo, "Generate Go files for tables/structs", flatbuffers::GeneralMakeRule },
"Generate Go files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java", true, { flatbuffers::GenerateGeneral, "-j", "--java", "Java", true,
flatbuffers::GenerateJavaGRPC, flatbuffers::GenerateJavaGRPC, flatbuffers::IDLOptions::kJava,
flatbuffers::IDLOptions::kJava,
"Generate Java classes for tables/structs", "Generate Java classes for tables/structs",
flatbuffers::GeneralMakeRule }, flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript", true, { flatbuffers::GenerateJS, "-s", "--js", "JavaScript", true, nullptr,
nullptr,
flatbuffers::IDLOptions::kJs, flatbuffers::IDLOptions::kJs,
"Generate JavaScript code for tables/structs", "Generate JavaScript code for tables/structs", flatbuffers::JSMakeRule },
flatbuffers::JSMakeRule }, { flatbuffers::GenerateJS, "-T", "--ts", "TypeScript", true, nullptr,
{ flatbuffers::GenerateJS, "-T", "--ts", "TypeScript", true,
nullptr,
flatbuffers::IDLOptions::kTs, flatbuffers::IDLOptions::kTs,
"Generate TypeScript code for tables/structs", "Generate TypeScript code for tables/structs", flatbuffers::JSMakeRule },
flatbuffers::JSMakeRule }, { flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", true, nullptr,
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", true,
nullptr,
flatbuffers::IDLOptions::kCSharp, flatbuffers::IDLOptions::kCSharp,
"Generate C# classes for tables/structs", "Generate C# classes for tables/structs", flatbuffers::GeneralMakeRule },
flatbuffers::GeneralMakeRule }, { flatbuffers::GeneratePython, "-p", "--python", "Python", true, nullptr,
{ flatbuffers::GeneratePython, "-p", "--python", "Python", true,
nullptr,
flatbuffers::IDLOptions::kPython, flatbuffers::IDLOptions::kPython,
"Generate Python files for tables/structs", "Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule }, flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP", true, { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", true, nullptr,
nullptr, flatbuffers::IDLOptions::kPhp, "Generate PHP files for tables/structs",
flatbuffers::IDLOptions::kPhp,
"Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJsonSchema, nullptr, "--jsonschema", "JsonSchema", true,
nullptr,
flatbuffers::IDLOptions::kJsonSchema,
"Generate Json schema",
flatbuffers::GeneralMakeRule }, flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJsonSchema, nullptr, "--jsonschema", "JsonSchema",
true, nullptr, flatbuffers::IDLOptions::kJsonSchema,
"Generate Json schema", flatbuffers::GeneralMakeRule },
}; };
flatbuffers::FlatCompiler::InitParams params; flatbuffers::FlatCompiler::InitParams params;

View File

@@ -14,17 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
#include <stdio.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include "flatbuffers/hash.h" #include "flatbuffers/hash.h"
#include <stdio.h>
enum OutputFormat { enum OutputFormat { kDecimal, kHexadecimal, kHexadecimal0x };
kDecimal,
kHexadecimal,
kHexadecimal0x
};
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
const char *name = argv[0]; const char *name = argv[0];
@@ -69,12 +65,18 @@ int main(int argc, char* argv[]) {
const char *arg = argv[i]; const char *arg = argv[i];
if (!escape_dash && arg[0] == '-') { if (!escape_dash && arg[0] == '-') {
std::string opt = arg; std::string opt = arg;
if (opt == "-d") output_format = kDecimal; if (opt == "-d")
else if (opt == "-x") output_format = kHexadecimal; output_format = kDecimal;
else if (opt == "-0x") output_format = kHexadecimal0x; else if (opt == "-x")
else if (opt == "-c") annotate = true; output_format = kHexadecimal;
else if (opt == "--") escape_dash = true; else if (opt == "-0x")
else printf("Unrecognized argument: \"%s\"\n", arg); output_format = kHexadecimal0x;
else if (opt == "-c")
annotate = true;
else if (opt == "--")
escape_dash = true;
else
printf("Unrecognized argument: \"%s\"\n", arg);
} else { } else {
std::stringstream ss; std::stringstream ss;
if (output_format == kDecimal) { if (output_format == kDecimal) {
@@ -90,8 +92,7 @@ int main(int argc, char* argv[]) {
else if (hash_function64) else if (hash_function64)
ss << hash_function64(arg); ss << hash_function64(arg);
if (annotate) if (annotate) ss << " /* \"" << arg << "\" */";
ss << " /* \"" << arg << "\" */";
ss << "\n"; ss << "\n";
@@ -100,4 +101,3 @@ int main(int argc, char* argv[]) {
} }
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -16,10 +16,10 @@
// independent from idl_parser, since this code is not needed for most clients // independent from idl_parser, since this code is not needed for most clients
#include "flatbuffers/code_generators.h"
#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 "flatbuffers/code_generators.h"
namespace flatbuffers { namespace flatbuffers {
@@ -28,8 +28,7 @@ static std::string GenType(const Type &type, bool underlying = false) {
case BASE_TYPE_STRUCT: case BASE_TYPE_STRUCT:
return type.struct_def->defined_namespace->GetFullyQualifiedName( return type.struct_def->defined_namespace->GetFullyQualifiedName(
type.struct_def->name); type.struct_def->name);
case BASE_TYPE_VECTOR: case BASE_TYPE_VECTOR: return "[" + GenType(type.VectorType()) + "]";
return "[" + GenType(type.VectorType()) + "]";
default: default:
if (type.enum_def && !underlying) { if (type.enum_def && !underlying) {
return type.enum_def->defined_namespace->GetFullyQualifiedName( return type.enum_def->defined_namespace->GetFullyQualifiedName(
@@ -69,6 +68,7 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
std::string schema; std::string schema;
schema += "// Generated from " + file_name + ".proto\n\n"; schema += "// Generated from " + file_name + ".proto\n\n";
if (parser.opts.include_dependence_headers) { if (parser.opts.include_dependence_headers) {
// clang-format off
#ifdef FBS_GEN_INCLUDES // TODO: currently all in one file. #ifdef FBS_GEN_INCLUDES // TODO: currently all in one file.
int num_includes = 0; int num_includes = 0;
for (auto it = parser.included_files_.begin(); for (auto it = parser.included_files_.begin();
@@ -82,6 +82,7 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
} }
if (num_includes) schema += "\n"; if (num_includes) schema += "\n";
#endif #endif
// clang-format on
} }
// Generate code for all the enum declarations. // Generate code for all the enum declarations.
const Namespace *last_namespace = nullptr; const Namespace *last_namespace = nullptr;
@@ -92,8 +93,8 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
GenComment(enum_def.doc_comment, &schema, nullptr); GenComment(enum_def.doc_comment, &schema, nullptr);
schema += "enum " + enum_def.name + " : "; schema += "enum " + enum_def.name + " : ";
schema += GenType(enum_def.underlying_type, true) + " {\n"; schema += GenType(enum_def.underlying_type, true) + " {\n";
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
it != enum_def.vals.vec.end(); ++it) { ++it) {
auto &ev = **it; auto &ev = **it;
GenComment(ev.doc_comment, &schema, nullptr, " "); GenComment(ev.doc_comment, &schema, nullptr, " ");
schema += " " + ev.name + " = " + NumToString(ev.value) + ",\n"; schema += " " + ev.name + " = " + NumToString(ev.value) + ",\n";
@@ -101,8 +102,8 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
schema += "}\n\n"; schema += "}\n\n";
} }
// Generate code for all structs/tables. // Generate code for all structs/tables.
for (auto it = parser.structs_.vec.begin(); for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
it != parser.structs_.vec.end(); ++it) { ++it) {
StructDef &struct_def = **it; StructDef &struct_def = **it;
GenNameSpace(*struct_def.defined_namespace, &schema, &last_namespace); GenNameSpace(*struct_def.defined_namespace, &schema, &last_namespace);
GenComment(struct_def.doc_comment, &schema, nullptr); GenComment(struct_def.doc_comment, &schema, nullptr);
@@ -123,12 +124,10 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
return schema; return schema;
} }
bool GenerateFBS(const Parser &parser, bool GenerateFBS(const Parser &parser, const std::string &path,
const std::string &path,
const std::string &file_name) { const std::string &file_name) {
return SaveFile((path + file_name + ".fbs").c_str(), return SaveFile((path + file_name + ".fbs").c_str(),
GenerateFBS(parser, file_name), false); GenerateFBS(parser, file_name), false);
} }
} // namespace flatbuffers } // namespace flatbuffers

View File

@@ -16,10 +16,10 @@
// independent from idl_parser, since this code is not needed for most clients // independent from idl_parser, since this code is not needed for most clients
#include "flatbuffers/code_generators.h"
#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 "flatbuffers/code_generators.h"
#if defined(FLATBUFFERS_CPP98_STL) #if defined(FLATBUFFERS_CPP98_STL)
# include <cctype> # include <cctype>
@@ -100,7 +100,8 @@ const LanguageParameters& GetLangParams(IDLOptions::Language lang) {
"", "",
"", "",
"", "",
"import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\nimport com.google.flatbuffers.*;\n", "import java.nio.*;\nimport java.lang.*;\nimport "
"java.util.*;\nimport com.google.flatbuffers.*;\n",
"\n@SuppressWarnings(\"unused\")\n", "\n@SuppressWarnings(\"unused\")\n",
{ {
"/**", "/**",
@@ -157,8 +158,7 @@ class GeneralGenerator : public BaseGenerator {
const std::string &file_name) const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "."), : BaseGenerator(parser, path, file_name, "", "."),
lang_(GetLangParams(parser_.opts.lang)), lang_(GetLangParams(parser_.opts.lang)),
cur_name_space_( nullptr ) { cur_name_space_(nullptr) {}
}
GeneralGenerator &operator=(const GeneralGenerator &); GeneralGenerator &operator=(const GeneralGenerator &);
bool generate() { bool generate() {
@@ -169,14 +169,14 @@ class GeneralGenerator : public BaseGenerator {
++it) { ++it) {
std::string enumcode; std::string enumcode;
auto &enum_def = **it; auto &enum_def = **it;
if (!parser_.opts.one_file) if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
cur_name_space_ = enum_def.defined_namespace;
GenEnum(enum_def, &enumcode); GenEnum(enum_def, &enumcode);
if (parser_.opts.one_file) { if (parser_.opts.one_file) {
one_file_code += enumcode; one_file_code += enumcode;
} else { } else {
if (!SaveType(enum_def.name, *enum_def.defined_namespace, if (!SaveType(enum_def.name, *enum_def.defined_namespace, enumcode,
enumcode, false)) return false; false))
return false;
} }
} }
@@ -190,14 +190,15 @@ class GeneralGenerator : public BaseGenerator {
if (parser_.opts.one_file) { if (parser_.opts.one_file) {
one_file_code += declcode; one_file_code += declcode;
} else { } else {
if (!SaveType(struct_def.name, *struct_def.defined_namespace, if (!SaveType(struct_def.name, *struct_def.defined_namespace, declcode,
declcode, true)) return false; true))
return false;
} }
} }
if (parser_.opts.one_file) { if (parser_.opts.one_file) {
return SaveType(file_name_, *parser_.current_namespace_, return SaveType(file_name_, *parser_.current_namespace_, one_file_code,
one_file_code, true); true);
} }
return true; return true;
} }
@@ -210,8 +211,11 @@ class GeneralGenerator : public BaseGenerator {
std::string code; std::string code;
if (lang_.language == IDLOptions::kCSharp) { if (lang_.language == IDLOptions::kCSharp) {
code = "// <auto-generated>\n" code =
"// " + std::string(FlatBuffersGeneratedWarning()) + "\n" "// <auto-generated>\n"
"// " +
std::string(FlatBuffersGeneratedWarning()) +
"\n"
"// </auto-generated>\n\n"; "// </auto-generated>\n\n";
} else { } else {
code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n"; code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
@@ -244,9 +248,10 @@ class GeneralGenerator : public BaseGenerator {
} }
std::string GenNullableAnnotation(const Type &t) { std::string GenNullableAnnotation(const Type &t) {
return lang_.language == IDLOptions::kJava return lang_.language == IDLOptions::kJava && parser_.opts.gen_nullable &&
&& parser_.opts.gen_nullable !IsScalar(DestinationType(t, true).base_type)
&& !IsScalar(DestinationType(t, true).base_type) ? " @Nullable ": ""; ? " @Nullable "
: "";
} }
static bool IsEnum(const Type &type) { static bool IsEnum(const Type &type) {
@@ -254,6 +259,7 @@ static bool IsEnum(const Type& type) {
} }
std::string GenTypeBasic(const Type &type, bool enableLangOverrides) { std::string GenTypeBasic(const Type &type, bool enableLangOverrides) {
// clang-format off
static const char *java_typename[] = { static const char *java_typename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
@@ -269,6 +275,7 @@ std::string GenTypeBasic(const Type &type, bool enableLangOverrides) {
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD #undef FLATBUFFERS_TD
}; };
// clang-format on
if (enableLangOverrides) { if (enableLangOverrides) {
if (lang_.language == IDLOptions::kCSharp) { if (lang_.language == IDLOptions::kCSharp) {
@@ -293,25 +300,19 @@ std::string GenTypeBasic(const Type &type) {
std::string GenTypePointer(const Type &type) { std::string GenTypePointer(const Type &type) {
switch (type.base_type) { switch (type.base_type) {
case BASE_TYPE_STRING: case BASE_TYPE_STRING: return lang_.string_type;
return lang_.string_type; case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
case BASE_TYPE_VECTOR: case BASE_TYPE_STRUCT: return WrapInNameSpace(*type.struct_def);
return GenTypeGet(type.VectorType());
case BASE_TYPE_STRUCT:
return WrapInNameSpace(*type.struct_def);
case BASE_TYPE_UNION: case BASE_TYPE_UNION:
// Unions in C# use a generic Table-derived type for better type safety // Unions in C# use a generic Table-derived type for better type safety
if (lang_.language == IDLOptions::kCSharp) return "TTable"; if (lang_.language == IDLOptions::kCSharp) return "TTable";
// fall through // fall through
default: default: return "Table";
return "Table";
} }
} }
std::string GenTypeGet(const Type &type) { std::string GenTypeGet(const Type &type) {
return IsScalar(type.base_type) return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
? GenTypeBasic(type)
: GenTypePointer(type);
} }
// Find the destination type the user wants to receive the value in (e.g. // Find the destination type the user wants to receive the value in (e.g.
@@ -319,14 +320,13 @@ std::string GenTypeGet(const Type &type) {
Type DestinationType(const Type &type, bool vectorelem) { Type DestinationType(const Type &type, bool vectorelem) {
if (lang_.language != IDLOptions::kJava) return type; if (lang_.language != IDLOptions::kJava) return type;
switch (type.base_type) { switch (type.base_type) {
// We use int for both uchar/ushort, since that generally means less casting // We use int for both uchar/ushort, since that generally means less
// than using short for uchar. // casting than using short for uchar.
case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT); case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT);
case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT); case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT);
case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG); case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG);
case BASE_TYPE_VECTOR: case BASE_TYPE_VECTOR:
if (vectorelem) if (vectorelem) return DestinationType(type.VectorType(), vectorelem);
return DestinationType(type.VectorType(), vectorelem);
// else fall thru // else fall thru
default: return type; default: return type;
} }
@@ -341,11 +341,10 @@ std::string GenOffsetType(const StructDef &struct_def) {
} }
std::string GenOffsetConstruct(const StructDef &struct_def, std::string GenOffsetConstruct(const StructDef &struct_def,
const std::string &variable_name) const std::string &variable_name) {
{
if (lang_.language == IDLOptions::kCSharp) { if (lang_.language == IDLOptions::kCSharp) {
return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + variable_name + return "new Offset<" + WrapInNameSpace(struct_def) + ">(" +
")"; variable_name + ")";
} }
return variable_name; return variable_name;
} }
@@ -359,8 +358,7 @@ std::string GenVectorOffsetType() {
} }
// Generate destination type name // Generate destination type name
std::string GenTypeNameDest(const Type &type) std::string GenTypeNameDest(const Type &type) {
{
return GenTypeGet(DestinationType(type, true)); return GenTypeGet(DestinationType(type, true));
} }
@@ -372,8 +370,7 @@ std::string DestinationMask(const Type &type, bool vectorelem) {
case BASE_TYPE_USHORT: return " & 0xFFFF"; case BASE_TYPE_USHORT: return " & 0xFFFF";
case BASE_TYPE_UINT: return " & 0xFFFFFFFFL"; case BASE_TYPE_UINT: return " & 0xFFFFFFFFL";
case BASE_TYPE_VECTOR: case BASE_TYPE_VECTOR:
if (vectorelem) if (vectorelem) return DestinationMask(type.VectorType(), vectorelem);
return DestinationMask(type.VectorType(), vectorelem);
// else fall thru // else fall thru
default: return ""; default: return "";
} }
@@ -395,8 +392,7 @@ std::string DestinationCast(const Type &type) {
if (IsEnum(type)) return "(" + WrapInNameSpace(*type.enum_def) + ")"; if (IsEnum(type)) return "(" + WrapInNameSpace(*type.enum_def) + ")";
break; break;
default: default: break;
break;
} }
} }
return ""; return "";
@@ -415,24 +411,24 @@ std::string SourceCast(const Type &type, bool castFromDest) {
switch (lang_.language) { switch (lang_.language) {
case IDLOptions::kJava: case IDLOptions::kJava:
if (castFromDest) { if (castFromDest) {
if (type.base_type == BASE_TYPE_UINT) return "(int)"; if (type.base_type == BASE_TYPE_UINT)
else if (type.base_type == BASE_TYPE_USHORT) return "(short)"; return "(int)";
else if (type.base_type == BASE_TYPE_UCHAR) return "(byte)"; else if (type.base_type == BASE_TYPE_USHORT)
return "(short)";
else if (type.base_type == BASE_TYPE_UCHAR)
return "(byte)";
} }
break; break;
case IDLOptions::kCSharp: case IDLOptions::kCSharp:
if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + ")"; if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + ")";
break; break;
default: default: break;
break;
} }
} }
return ""; return "";
} }
std::string SourceCast(const Type &type) { std::string SourceCast(const Type &type) { return SourceCast(type, true); }
return SourceCast(type, true);
}
std::string SourceCastBasic(const Type &type, bool castFromDest) { std::string SourceCastBasic(const Type &type, bool castFromDest) {
return IsScalar(type.base_type) ? SourceCast(type, castFromDest) : ""; return IsScalar(type.base_type) ? SourceCast(type, castFromDest) : "";
@@ -442,7 +438,6 @@ std::string SourceCastBasic(const Type &type) {
return SourceCastBasic(type, true); return SourceCastBasic(type, true);
} }
std::string GenEnumDefaultValue(const Value &value) { std::string GenEnumDefaultValue(const Value &value) {
auto enum_def = value.type.enum_def; auto enum_def = value.type.enum_def;
auto vec = enum_def->vals.vec; auto vec = enum_def->vals.vec;
@@ -474,10 +469,8 @@ std::string GenDefaultValue(const Value &value, bool enableLangOverrides) {
switch (value.type.base_type) { switch (value.type.base_type) {
case BASE_TYPE_FLOAT: return value.constant + "f"; case BASE_TYPE_FLOAT: return value.constant + "f";
case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true"; case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true";
case BASE_TYPE_ULONG: case BASE_TYPE_ULONG: {
{ if (lang_.language != IDLOptions::kJava) return value.constant;
if (lang_.language != IDLOptions::kJava)
return value.constant;
// Converts the ulong into its bits signed equivalent // Converts the ulong into its bits signed equivalent
uint64_t defaultValue = StringToUInt(value.constant.c_str()); uint64_t defaultValue = StringToUInt(value.constant.c_str());
return NumToString(static_cast<int64_t>(defaultValue)) + longSuffix; return NumToString(static_cast<int64_t>(defaultValue)) + longSuffix;
@@ -492,20 +485,18 @@ std::string GenDefaultValue(const Value &value) {
return GenDefaultValue(value, true); return GenDefaultValue(value, true);
} }
std::string GenDefaultValueBasic(const Value &value, bool enableLangOverrides) { std::string GenDefaultValueBasic(const Value &value,
bool enableLangOverrides) {
if (!IsScalar(value.type.base_type)) { if (!IsScalar(value.type.base_type)) {
if (enableLangOverrides) { if (enableLangOverrides) {
if (lang_.language == IDLOptions::kCSharp) { if (lang_.language == IDLOptions::kCSharp) {
switch (value.type.base_type) { switch (value.type.base_type) {
case BASE_TYPE_STRING: case BASE_TYPE_STRING: return "default(StringOffset)";
return "default(StringOffset)";
case BASE_TYPE_STRUCT: case BASE_TYPE_STRUCT:
return "default(Offset<" + WrapInNameSpace(*value.type.struct_def) + return "default(Offset<" +
">)"; WrapInNameSpace(*value.type.struct_def) + ">)";
case BASE_TYPE_VECTOR: case BASE_TYPE_VECTOR: return "default(VectorOffset)";
return "default(VectorOffset)"; default: break;
default:
break;
} }
} }
} }
@@ -537,8 +528,7 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr) {
if (lang_.language == IDLOptions::kJava) { if (lang_.language == IDLOptions::kJava) {
code += " private " + enum_def.name + "() { }\n"; code += " private " + enum_def.name + "() { }\n";
} }
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
it != enum_def.vals.vec.end();
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
GenComment(ev.doc_comment, code_ptr, &lang_.comment_config, " "); GenComment(ev.doc_comment, code_ptr, &lang_.comment_config, " ");
@@ -563,14 +553,14 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr) {
// Average distance between values above which we consider a table // Average distance between values above which we consider a table
// "too sparse". Change at will. // "too sparse". Change at will.
static const int kMaxSparseness = 5; static const int kMaxSparseness = 5;
if (range / static_cast<int64_t>(enum_def.vals.vec.size()) < kMaxSparseness) { if (range / static_cast<int64_t>(enum_def.vals.vec.size()) <
kMaxSparseness) {
code += "\n public static"; code += "\n public static";
code += lang_.const_decl; code += lang_.const_decl;
code += lang_.string_type; code += lang_.string_type;
code += "[] names = { "; code += "[] names = { ";
auto val = enum_def.vals.vec.front()->value; auto val = enum_def.vals.vec.front()->value;
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
it != enum_def.vals.vec.end();
++it) { ++it) {
while (val++ != (*it)->value) code += "\"\", "; while (val++ != (*it)->value) code += "\"\", ";
code += "\"" + (*it)->name + "\", "; code += "\"" + (*it)->name + "\", ";
@@ -624,8 +614,8 @@ std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field,
if (GenTypeBasic(type, false) != "byte") { if (GenTypeBasic(type, false) != "byte") {
getter += MakeCamel(GenTypeBasic(type, false)); getter += MakeCamel(GenTypeBasic(type, false));
} }
getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")" getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")" +
+ dest_mask; dest_mask;
return getter; return getter;
} }
@@ -647,8 +637,7 @@ std::string GenSetter(const Type &type) {
// Returns the method name for use with add/put calls. // Returns the method name for use with add/put calls.
std::string GenMethod(const Type &type) { std::string GenMethod(const Type &type) {
return IsScalar(type.base_type) return IsScalar(type.base_type) ? MakeCamel(GenTypeBasic(type, false))
? MakeCamel(GenTypeBasic(type, false))
: (IsStruct(type) ? "Struct" : "Offset"); : (IsStruct(type) ? "Struct" : "Offset");
} }
@@ -658,8 +647,7 @@ void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
const char *nameprefix) { const char *nameprefix) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
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 (IsStruct(field.value.type)) { if (IsStruct(field.value.type)) {
// Generate arguments for a struct inside a struct. To ensure names // Generate arguments for a struct inside a struct. To ensure names
@@ -700,7 +688,8 @@ void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
code += " builder." + FunctionStart('P') + "ut"; code += " builder." + FunctionStart('P') + "ut";
code += GenMethod(field.value.type) + "("; code += GenMethod(field.value.type) + "(";
code += SourceCast(field.value.type); code += SourceCast(field.value.type);
auto argname = nameprefix + MakeCamel(field.name, lang_.first_camel_upper); auto argname =
nameprefix + MakeCamel(field.name, lang_.first_camel_upper);
code += argname; code += argname;
code += ");\n"; code += ");\n";
} }
@@ -709,8 +698,10 @@ void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
std::string GenByteBufferLength(const char *bb_name) { std::string GenByteBufferLength(const char *bb_name) {
std::string bb_len = bb_name; std::string bb_len = bb_name;
if (lang_.language == IDLOptions::kCSharp) bb_len += ".Length"; if (lang_.language == IDLOptions::kCSharp)
else bb_len += ".capacity()"; bb_len += ".Length";
else
bb_len += ".capacity()";
return bb_len; return bb_len;
} }
@@ -721,8 +712,9 @@ std::string GenOffsetGetter(flatbuffers::FieldDef *key_field,
NumToString(key_field->value.offset) + ", "; NumToString(key_field->value.offset) + ", ";
if (num) { if (num) {
key_offset += num; key_offset += num;
key_offset += (lang_.language == IDLOptions::kCSharp ? key_offset +=
".Value, builder.DataBuffer)" : ", _bb)"); (lang_.language == IDLOptions::kCSharp ? ".Value, builder.DataBuffer)"
: ", _bb)");
} else { } else {
key_offset += GenByteBufferLength("bb"); key_offset += GenByteBufferLength("bb");
key_offset += " - tableOffset, bb)"; key_offset += " - tableOffset, bb)";
@@ -753,35 +745,33 @@ std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) {
return key_getter; return key_getter;
} }
std::string GenKeyGetter(flatbuffers::FieldDef *key_field) { std::string GenKeyGetter(flatbuffers::FieldDef *key_field) {
std::string key_getter = ""; std::string key_getter = "";
auto data_buffer = (lang_.language == IDLOptions::kCSharp) ? auto data_buffer =
"builder.DataBuffer" : "_bb"; (lang_.language == IDLOptions::kCSharp) ? "builder.DataBuffer" : "_bb";
if (key_field->value.type.base_type == BASE_TYPE_STRING) { if (key_field->value.type.base_type == BASE_TYPE_STRING) {
if (lang_.language == IDLOptions::kJava) if (lang_.language == IDLOptions::kJava) key_getter += " return ";
key_getter += " return ";
key_getter += lang_.accessor_prefix_static; key_getter += lang_.accessor_prefix_static;
key_getter += FunctionStart('C') + "ompareStrings("; key_getter += FunctionStart('C') + "ompareStrings(";
key_getter += GenOffsetGetter(key_field, "o1") + ", "; key_getter += GenOffsetGetter(key_field, "o1") + ", ";
key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")"; key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")";
if (lang_.language == IDLOptions::kJava) if (lang_.language == IDLOptions::kJava) key_getter += ";";
key_getter += ";"; } else {
}
else {
auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1"); auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1");
if (lang_.language == IDLOptions::kCSharp) { if (lang_.language == IDLOptions::kCSharp) {
key_getter += field_getter; key_getter += field_getter;
field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2"); field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2");
key_getter += ".CompareTo(" + field_getter + ")"; key_getter += ".CompareTo(" + field_getter + ")";
} } else {
else { key_getter +=
key_getter += "\n " + GenTypeNameDest(key_field->value.type) + " val_1 = "; "\n " + GenTypeNameDest(key_field->value.type) + " val_1 = ";
key_getter += field_getter + ";\n " + GenTypeNameDest(key_field->value.type); key_getter +=
field_getter + ";\n " + GenTypeNameDest(key_field->value.type);
key_getter += " val_2 = "; key_getter += " val_2 = ";
field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2"); field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2");
key_getter += field_getter + ";\n"; key_getter += field_getter + ";\n";
key_getter += " return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n "; key_getter +=
" return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n ";
} }
} }
return key_getter; return key_getter;
@@ -826,16 +816,19 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
if (!struct_def.fixed) { if (!struct_def.fixed) {
// Generate a special accessor for the table that when used as the root // Generate a special accessor for the table that when used as the root
// of a FlatBuffer // of a FlatBuffer
std::string method_name = FunctionStart('G') + "etRootAs" + struct_def.name; std::string method_name =
std::string method_signature = " public static " + struct_def.name + " " + FunctionStart('G') + "etRootAs" + struct_def.name;
method_name; std::string method_signature =
" public static " + struct_def.name + " " + method_name;
// create convenience method that doesn't require an existing object // create convenience method that doesn't require an existing object
code += method_signature + "(ByteBuffer _bb) "; code += method_signature + "(ByteBuffer _bb) ";
code += "{ return " + method_name + "(_bb, new " + struct_def.name+ "()); }\n"; code += "{ return " + method_name + "(_bb, new " + struct_def.name +
"()); }\n";
// create method that allows object reuse // create method that allows object reuse
code += method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { "; code +=
method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { ";
code += lang_.set_bb_byteorder; code += lang_.set_bb_byteorder;
code += "return (obj.__assign(_bb." + FunctionStart('G') + "etInt(_bb."; code += "return (obj.__assign(_bb." + FunctionStart('G') + "etInt(_bb.";
code += lang_.get_bb_position; code += lang_.get_bb_position;
@@ -859,11 +852,11 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += " public void __init(int _i, ByteBuffer _bb) "; code += " public void __init(int _i, ByteBuffer _bb) ";
code += "{ " + lang_.accessor_prefix + "bb_pos = _i; "; code += "{ " + lang_.accessor_prefix + "bb_pos = _i; ";
code += lang_.accessor_prefix + "bb = _bb; }\n"; code += lang_.accessor_prefix + "bb = _bb; }\n";
code += " public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) "; code +=
" public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) ";
code += "{ __init(_i, _bb); return this; }\n\n"; code += "{ __init(_i, _bb); return this; }\n\n";
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) continue; if (field.deprecated) continue;
GenComment(field.doc_comment, code_ptr, &lang_.comment_config, " "); GenComment(field.doc_comment, code_ptr, &lang_.comment_config, " ");
@@ -871,8 +864,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
std::string type_name_dest = GenTypeNameDest(field.value.type); std::string type_name_dest = GenTypeNameDest(field.value.type);
std::string conditional_cast = ""; std::string conditional_cast = "";
std::string optional = ""; std::string optional = "";
if (lang_.language == IDLOptions::kCSharp && if (lang_.language == IDLOptions::kCSharp && !struct_def.fixed &&
!struct_def.fixed &&
(field.value.type.base_type == BASE_TYPE_STRUCT || (field.value.type.base_type == BASE_TYPE_STRUCT ||
field.value.type.base_type == BASE_TYPE_UNION || field.value.type.base_type == BASE_TYPE_UNION ||
(field.value.type.base_type == BASE_TYPE_VECTOR && (field.value.type.base_type == BASE_TYPE_VECTOR &&
@@ -883,7 +875,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
std::string dest_mask = DestinationMask(field.value.type, true); std::string dest_mask = DestinationMask(field.value.type, true);
std::string dest_cast = DestinationCast(field.value.type); std::string dest_cast = DestinationCast(field.value.type);
std::string src_cast = SourceCast(field.value.type); std::string src_cast = SourceCast(field.value.type);
std::string method_start = " public " + GenNullableAnnotation(field.value.type) + std::string method_start = " public " +
GenNullableAnnotation(field.value.type) +
type_name_dest + optional + " " + type_name_dest + optional + " " +
MakeCamel(field.name, lang_.first_camel_upper); MakeCamel(field.name, lang_.first_camel_upper);
std::string obj = lang_.language == IDLOptions::kCSharp std::string obj = lang_.language == IDLOptions::kCSharp
@@ -1004,8 +997,11 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
} }
code += ")" + dest_mask + " : "; code += ")" + dest_mask + " : ";
code += field.value.type.element == BASE_TYPE_BOOL ? "false" : code +=
(IsScalar(field.value.type.element) ? default_cast + "0" : "null"); field.value.type.element == BASE_TYPE_BOOL
? "false"
: (IsScalar(field.value.type.element) ? default_cast + "0"
: "null");
break; break;
} }
case BASE_TYPE_UNION: case BASE_TYPE_UNION:
@@ -1018,14 +1014,14 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "(obj, o) : null"; code += "(obj, o) : null";
} }
break; break;
default: default: assert(0);
assert(0);
} }
} }
code += member_suffix; code += member_suffix;
code += "}\n"; code += "}\n";
if (field.value.type.base_type == BASE_TYPE_VECTOR) { if (field.value.type.base_type == BASE_TYPE_VECTOR) {
code += " public int " + MakeCamel(field.name, lang_.first_camel_upper); code +=
" public int " + MakeCamel(field.name, lang_.first_camel_upper);
code += "Length"; code += "Length";
code += lang_.getter_prefix; code += lang_.getter_prefix;
code += offset_prefix; code += offset_prefix;
@@ -1064,7 +1060,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "AsByteBuffer() { return "; code += "AsByteBuffer() { return ";
code += lang_.accessor_prefix + "__vector_as_bytebuffer("; code += lang_.accessor_prefix + "__vector_as_bytebuffer(";
code += NumToString(field.value.offset) + ", "; code += NumToString(field.value.offset) + ", ";
code += NumToString(field.value.type.base_type == BASE_TYPE_STRING code +=
NumToString(field.value.type.base_type == BASE_TYPE_STRING
? 1 ? 1
: InlineSize(field.value.type.VectorType())); : InlineSize(field.value.type.VectorType()));
code += "); }\n"; code += "); }\n";
@@ -1077,24 +1074,26 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += NumToString(field.value.offset); code += NumToString(field.value.offset);
code += "); }\n"; code += "); }\n";
break; break;
default: default: break;
break;
} }
} }
// generate object accessors if is nested_flatbuffer // generate object accessors if is nested_flatbuffer
if (field.nested_flatbuffer) { if (field.nested_flatbuffer) {
auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer); auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
auto nested_method_name = MakeCamel(field.name, lang_.first_camel_upper) auto nested_method_name =
+ "As" + nested_type_name; MakeCamel(field.name, lang_.first_camel_upper) + "As" +
nested_type_name;
auto get_nested_method_name = nested_method_name; auto get_nested_method_name = nested_method_name;
if (lang_.language == IDLOptions::kCSharp) { if (lang_.language == IDLOptions::kCSharp) {
get_nested_method_name = "Get" + nested_method_name; get_nested_method_name = "Get" + nested_method_name;
conditional_cast = "(" + nested_type_name + lang_.optional_suffix + ")"; conditional_cast =
"(" + nested_type_name + lang_.optional_suffix + ")";
} }
if (lang_.language != IDLOptions::kCSharp) { if (lang_.language != IDLOptions::kCSharp) {
code += " public " + nested_type_name + lang_.optional_suffix + " "; code += " public " + nested_type_name + lang_.optional_suffix + " ";
code += nested_method_name + "() { return "; code += nested_method_name + "() { return ";
code += get_nested_method_name + "(new " + nested_type_name + "()); }\n"; code +=
get_nested_method_name + "(new " + nested_type_name + "()); }\n";
} else { } else {
obj = "(new " + nested_type_name + "())"; obj = "(new " + nested_type_name + "())";
} }
@@ -1122,10 +1121,12 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
auto mutator_prefix = MakeCamel("mutate", lang_.first_camel_upper); auto mutator_prefix = MakeCamel("mutate", lang_.first_camel_upper);
// A vector mutator also needs the index of the vector element it should // A vector mutator also needs the index of the vector element it should
// mutate. // mutate.
auto mutator_params = (field.value.type.base_type == BASE_TYPE_VECTOR auto mutator_params =
? "(int j, " (field.value.type.base_type == BASE_TYPE_VECTOR ? "(int j, "
: "(") + GenTypeNameDest(underlying_type) + " " + field.name + ") { "; : "(") +
auto setter_index = field.value.type.base_type == BASE_TYPE_VECTOR GenTypeNameDest(underlying_type) + " " + field.name + ") { ";
auto setter_index =
field.value.type.base_type == BASE_TYPE_VECTOR
? lang_.accessor_prefix + "__vector(o) + j * " + ? lang_.accessor_prefix + "__vector(o) + j * " +
NumToString(InlineSize(underlying_type)) NumToString(InlineSize(underlying_type))
: (struct_def.fixed : (struct_def.fixed
@@ -1163,8 +1164,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += ") {\n"; code += ") {\n";
GenStructBody(struct_def, code_ptr, ""); GenStructBody(struct_def, code_ptr, "");
code += " return "; code += " return ";
code += GenOffsetConstruct(struct_def, code += GenOffsetConstruct(
"builder." + std::string(lang_.get_fbb_offset)); struct_def, "builder." + std::string(lang_.get_fbb_offset));
code += ";\n }\n"; code += ";\n }\n";
} else { } else {
// Generate a method that creates a table in one go. This is only possible // Generate a method that creates a table in one go. This is only possible
@@ -1211,8 +1212,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += FunctionStart('S') + "tartObject("; code += FunctionStart('S') + "tartObject(";
code += NumToString(struct_def.fields.vec.size()) + ");\n"; code += NumToString(struct_def.fields.vec.size()) + ");\n";
for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
size; size; size /= 2) {
size /= 2) {
for (auto it = struct_def.fields.vec.rbegin(); for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) { it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it; auto &field = **it;
@@ -1296,7 +1296,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "); return "; code += "); return ";
code += "builder." + FunctionStart('E') + "ndVector(); }\n"; code += "builder." + FunctionStart('E') + "ndVector(); }\n";
} }
// Generate a method to start a vector, data to be added manually after. // Generate a method to start a vector, data to be added manually
// after.
code += " public static void " + FunctionStart('S') + "tart"; code += " public static void " + FunctionStart('S') + "tart";
code += MakeCamel(field.name); code += MakeCamel(field.name);
code += "Vector(FlatBufferBuilder builder, int numElems) "; code += "Vector(FlatBufferBuilder builder, int numElems) ";
@@ -1311,8 +1312,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "(FlatBufferBuilder builder) {\n int o = builder."; code += "(FlatBufferBuilder builder) {\n int o = builder.";
code += FunctionStart('E') + "ndObject();\n"; code += FunctionStart('E') + "ndObject();\n";
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 && field.required) { if (!field.deprecated && field.required) {
code += " builder." + FunctionStart('R') + "equired(o, "; code += " builder." + FunctionStart('R') + "equired(o, ";
@@ -1324,12 +1324,11 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
if (parser_.root_struct_def_ == &struct_def) { if (parser_.root_struct_def_ == &struct_def) {
code += " public static void "; code += " public static void ";
code += FunctionStart('F') + "inish" + struct_def.name; code += FunctionStart('F') + "inish" + struct_def.name;
code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def); code +=
"Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def);
code += " offset) {"; code += " offset) {";
code += " builder." + FunctionStart('F') + "inish(offset"; code += " builder." + FunctionStart('F') + "inish(offset";
if (lang_.language == IDLOptions::kCSharp) { if (lang_.language == IDLOptions::kCSharp) { code += ".Value"; }
code += ".Value";
}
if (parser_.file_identifier_.length()) if (parser_.file_identifier_.length())
code += ", \"" + parser_.file_identifier_ + "\""; code += ", \"" + parser_.file_identifier_ + "\"";
@@ -1344,15 +1343,15 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "Integer o1, Integer o2, ByteBuffer _bb) {"; code += "Integer o1, Integer o2, ByteBuffer _bb) {";
code += GenKeyGetter(key_field); code += GenKeyGetter(key_field);
code += " }\n"; code += " }\n";
} } else {
else {
code += "\n public static VectorOffset "; code += "\n public static VectorOffset ";
code += "CreateSortedVectorOf" + struct_def.name; code += "CreateSortedVectorOf" + struct_def.name;
code += "(FlatBufferBuilder builder, "; code += "(FlatBufferBuilder builder, ";
code += "Offset<" + struct_def.name + ">"; code += "Offset<" + struct_def.name + ">";
code += "[] offsets) {\n"; code += "[] offsets) {\n";
code += " Array.Sort(offsets, (Offset<" + struct_def.name + code += " Array.Sort(offsets, (Offset<" + struct_def.name +
"> o1, Offset<" + struct_def.name + "> o2) => " + GenKeyGetter(key_field); "> o1, Offset<" + struct_def.name + "> o2) => " +
GenKeyGetter(key_field);
code += ");\n"; code += ");\n";
code += " return builder.CreateVectorOfTables(offsets);\n }\n"; code += " return builder.CreateVectorOfTables(offsets);\n }\n";
} }
@@ -1393,7 +1392,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "\n\n"; code += "\n\n";
} }
const LanguageParameters &lang_; const LanguageParameters &lang_;
// This tracks the current namespace used to determine if a type need to be prefixed by its namespace // This tracks the current namespace used to determine if a type need to be
// prefixed by its namespace
const Namespace *cur_name_space_; const Namespace *cur_name_space_;
}; };
} // namespace general } // namespace general
@@ -1424,9 +1424,8 @@ std::string GeneralMakeRule(const Parser &parser, const std::string &path,
++it) { ++it) {
auto &struct_def = **it; auto &struct_def = **it;
if (make_rule != "") make_rule += " "; if (make_rule != "") make_rule += " ";
std::string directory = std::string directory = BaseGenerator::NamespaceDir(
BaseGenerator::NamespaceDir(parser, path, parser, path, *struct_def.defined_namespace);
*struct_def.defined_namespace);
make_rule += directory + struct_def.name + lang.file_extension; make_rule += directory + struct_def.name + lang.file_extension;
} }
@@ -1438,36 +1437,31 @@ std::string GeneralMakeRule(const Parser &parser, const std::string &path,
return make_rule; return make_rule;
} }
std::string BinaryFileName(const Parser &parser, std::string BinaryFileName(const Parser &parser, const std::string &path,
const std::string &path,
const std::string &file_name) { const std::string &file_name) {
auto ext = parser.file_extension_.length() ? parser.file_extension_ : "bin"; auto ext = parser.file_extension_.length() ? parser.file_extension_ : "bin";
return path + file_name + "." + ext; return path + file_name + "." + ext;
} }
bool GenerateBinary(const Parser &parser, bool GenerateBinary(const Parser &parser, const std::string &path,
const std::string &path,
const std::string &file_name) { const std::string &file_name) {
return !parser.builder_.GetSize() || return !parser.builder_.GetSize() ||
flatbuffers::SaveFile( flatbuffers::SaveFile(
BinaryFileName(parser, path, file_name).c_str(), BinaryFileName(parser, path, file_name).c_str(),
reinterpret_cast<char *>(parser.builder_.GetBufferPointer()), reinterpret_cast<char *>(parser.builder_.GetBufferPointer()),
parser.builder_.GetSize(), parser.builder_.GetSize(), true);
true);
} }
std::string BinaryMakeRule(const Parser &parser, std::string BinaryMakeRule(const Parser &parser, const std::string &path,
const std::string &path,
const std::string &file_name) { const std::string &file_name) {
if (!parser.builder_.GetSize()) return ""; if (!parser.builder_.GetSize()) return "";
std::string filebase = flatbuffers::StripPath( std::string filebase =
flatbuffers::StripExtension(file_name)); flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
std::string make_rule = BinaryFileName(parser, path, filebase) + ": " + std::string make_rule =
file_name; BinaryFileName(parser, path, filebase) + ": " + file_name;
auto included_files = parser.GetIncludedFilesRecursive( auto included_files =
parser.root_struct_def_->file); parser.GetIncludedFilesRecursive(parser.root_struct_def_->file);
for (auto it = included_files.begin(); for (auto it = included_files.begin(); it != included_files.end(); ++it) {
it != included_files.end(); ++it) {
make_rule += " " + *it; make_rule += " " + *it;
} }
return make_rule; return make_rule;

View File

@@ -16,13 +16,13 @@
// independent from idl_parser, since this code is not needed for most clients // independent from idl_parser, since this code is not needed for most clients
#include <string>
#include <sstream> #include <sstream>
#include <string>
#include "flatbuffers/code_generators.h"
#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 "flatbuffers/code_generators.h"
#ifdef _WIN32 #ifdef _WIN32
# include <direct.h> # include <direct.h>
@@ -44,9 +44,10 @@ namespace go {
// see https://golang.org/ref/spec#Keywords // see https://golang.org/ref/spec#Keywords
static const char *g_golang_keywords[] = { static const char *g_golang_keywords[] = {
"break", "default", "func", "interface", "select", "case", "defer", "go", "break", "default", "func", "interface", "select", "case", "defer",
"map", "struct", "chan", "else", "goto", "package", "switch", "const", "go", "map", "struct", "chan", "else", "goto", "package",
"fallthrough", "if", "range", "type", "continue", "for", "import", "return", "var", "switch", "const", "fallthrough", "if", "range", "type", "continue",
"for", "import", "return", "var",
}; };
static std::string GenGetter(const Type &type); static std::string GenGetter(const Type &type);
@@ -58,22 +59,19 @@ static std::string GenTypeBasic(const Type &type);
static std::string GenTypeGet(const Type &type); static std::string GenTypeGet(const Type &type);
static std::string TypeName(const FieldDef &field); static std::string TypeName(const FieldDef &field);
static std::string GoIdentity(const std::string &name) { static std::string GoIdentity(const std::string &name) {
for (size_t i=0; i<sizeof(g_golang_keywords)/sizeof(g_golang_keywords[0]); i++) { for (size_t i = 0;
if (name == g_golang_keywords[i]) { i < sizeof(g_golang_keywords) / sizeof(g_golang_keywords[0]); i++) {
return MakeCamel(name + "_", false); if (name == g_golang_keywords[i]) { return MakeCamel(name + "_", false); }
}
} }
return MakeCamel(name, false); return MakeCamel(name, false);
} }
// Most field accessors need to retrieve and test the field offset first, // Most field accessors need to retrieve and test the field offset first,
// this is the prefix code for that. // this is the prefix code for that.
std::string OffsetPrefix(const FieldDef &field) { std::string OffsetPrefix(const FieldDef &field) {
return "{\n\to := flatbuffers.UOffsetT(rcv._tab.Offset(" + return "{\n\to := flatbuffers.UOffsetT(rcv._tab.Offset(" +
NumToString(field.value.offset) + NumToString(field.value.offset) + "))\n\tif o != 0 {\n";
"))\n\tif o != 0 {\n";
} }
// Begin a class declaration. // Begin a class declaration.
@@ -185,8 +183,7 @@ static void GenTableAccessor(const StructDef &struct_def,
} }
// Get the length of a vector. // Get the length of a vector.
static void GetVectorLen(const StructDef &struct_def, static void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
const FieldDef &field,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
@@ -198,8 +195,7 @@ static void GetVectorLen(const StructDef &struct_def,
} }
// Get a [ubyte] vector as a byte slice. // Get a [ubyte] vector as a byte slice.
static void GetUByteSlice(const StructDef &struct_def, static void GetUByteSlice(const StructDef &struct_def, const FieldDef &field,
const FieldDef &field,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
@@ -284,8 +280,7 @@ static void GetStructFieldOfTable(const StructDef &struct_def,
} }
// Get the value of a string. // Get the value of a string.
static void GetStringField(const StructDef &struct_def, static void GetStringField(const StructDef &struct_def, const FieldDef &field,
const FieldDef &field,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr); GenReceiver(struct_def, code_ptr);
@@ -297,8 +292,7 @@ static void GetStringField(const StructDef &struct_def,
} }
// Get the value of a union from an object. // Get the value of a union from an object.
static void GetUnionField(const StructDef &struct_def, static void GetUnionField(const StructDef &struct_def, const FieldDef &field,
const FieldDef &field,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr); GenReceiver(struct_def, code_ptr);
@@ -375,19 +369,16 @@ static void BeginBuilderArgs(const StructDef &struct_def,
// Recursively generate arguments for a constructor, to deal with nested // Recursively generate arguments for a constructor, to deal with nested
// structs. // structs.
static void StructBuilderArgs(const StructDef &struct_def, static void StructBuilderArgs(const StructDef &struct_def,
const char *nameprefix, const char *nameprefix, std::string *code_ptr) {
std::string *code_ptr) {
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 (IsStruct(field.value.type)) { if (IsStruct(field.value.type)) {
// Generate arguments for a struct inside a struct. To ensure names // Generate arguments for a struct inside a struct. To ensure names
// don't clash, and to make it obvious these arguments are constructing // don't clash, and to make it obvious these arguments are constructing
// a nested struct, prefix the name with the field name. // a nested struct, prefix the name with the field name.
StructBuilderArgs(*field.value.type.struct_def, StructBuilderArgs(*field.value.type.struct_def,
(nameprefix + (field.name + "_")).c_str(), (nameprefix + (field.name + "_")).c_str(), code_ptr);
code_ptr);
} else { } else {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += (std::string) ", " + nameprefix; code += (std::string) ", " + nameprefix;
@@ -406,21 +397,18 @@ static void EndBuilderArgs(std::string *code_ptr) {
// Recursively generate struct construction statements and instert manual // Recursively generate struct construction statements and instert manual
// padding. // padding.
static void StructBuilderBody(const StructDef &struct_def, static void StructBuilderBody(const StructDef &struct_def,
const char *nameprefix, const char *nameprefix, std::string *code_ptr) {
std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += "\tbuilder.Prep(" + NumToString(struct_def.minalign) + ", "; code += "\tbuilder.Prep(" + NumToString(struct_def.minalign) + ", ";
code += NumToString(struct_def.bytesize) + ")\n"; code += NumToString(struct_def.bytesize) + ")\n";
for (auto it = struct_def.fields.vec.rbegin(); for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); it != struct_def.fields.vec.rend(); ++it) {
++it) {
auto &field = **it; auto &field = **it;
if (field.padding) if (field.padding)
code += "\tbuilder.Pad(" + NumToString(field.padding) + ")\n"; code += "\tbuilder.Pad(" + NumToString(field.padding) + ")\n";
if (IsStruct(field.value.type)) { if (IsStruct(field.value.type)) {
StructBuilderBody(*field.value.type.struct_def, StructBuilderBody(*field.value.type.struct_def,
(nameprefix + (field.name + "_")).c_str(), (nameprefix + (field.name + "_")).c_str(), code_ptr);
code_ptr);
} else { } else {
code += "\tbuilder.Prepend" + GenMethod(field) + "("; code += "\tbuilder.Prepend" + GenMethod(field) + "(";
code += nameprefix + GoIdentity(field.name) + ")\n"; code += nameprefix + GoIdentity(field.name) + ")\n";
@@ -447,8 +435,7 @@ static void GetStartOfTable(const StructDef &struct_def,
// Set the value of a table's field. // Set the value of a table's field.
static void BuildFieldOfTable(const StructDef &struct_def, static void BuildFieldOfTable(const StructDef &struct_def,
const FieldDef &field, const FieldDef &field, const size_t offset,
const size_t offset,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += "func " + struct_def.name + "Add" + MakeCamel(field.name); code += "func " + struct_def.name + "Add" + MakeCamel(field.name);
@@ -476,8 +463,7 @@ static void BuildFieldOfTable(const StructDef &struct_def,
// Set the value of one of the members of a table's vector. // Set the value of one of the members of a table's vector.
static void BuildVectorOfTable(const StructDef &struct_def, static void BuildVectorOfTable(const StructDef &struct_def,
const FieldDef &field, const FieldDef &field, std::string *code_ptr) {
std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += "func " + struct_def.name + "Start"; code += "func " + struct_def.name + "Start";
code += MakeCamel(field.name); code += MakeCamel(field.name);
@@ -508,8 +494,7 @@ static void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
// Generate a struct field getter, conditioned on its child type(s). // Generate a struct field getter, conditioned on its child type(s).
static void GenStructAccessor(const StructDef &struct_def, static void GenStructAccessor(const StructDef &struct_def,
const FieldDef &field, const FieldDef &field, std::string *code_ptr) {
std::string *code_ptr) {
GenComment(field.doc_comment, code_ptr, nullptr, ""); GenComment(field.doc_comment, code_ptr, nullptr, "");
if (IsScalar(field.value.type.base_type)) { if (IsScalar(field.value.type.base_type)) {
if (struct_def.fixed) { if (struct_def.fixed) {
@@ -526,9 +511,7 @@ static void GenStructAccessor(const StructDef &struct_def,
GetStructFieldOfTable(struct_def, field, code_ptr); GetStructFieldOfTable(struct_def, field, code_ptr);
} }
break; break;
case BASE_TYPE_STRING: case BASE_TYPE_STRING: GetStringField(struct_def, field, code_ptr); break;
GetStringField(struct_def, field, code_ptr);
break;
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType(); auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_STRUCT) { if (vectortype.base_type == BASE_TYPE_STRUCT) {
@@ -538,11 +521,8 @@ static void GenStructAccessor(const StructDef &struct_def,
} }
break; break;
} }
case BASE_TYPE_UNION: case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
GetUnionField(struct_def, field, code_ptr); default: assert(0);
break;
default:
assert(0);
} }
} }
if (field.value.type.base_type == BASE_TYPE_VECTOR) { if (field.value.type.base_type == BASE_TYPE_VECTOR) {
@@ -582,8 +562,7 @@ static void MutateScalarFieldOfTable(const StructDef &struct_def,
} }
// Generate a struct field setter, conditioned on its child type(s). // Generate a struct field setter, conditioned on its child type(s).
static void GenStructMutator(const StructDef &struct_def, static void GenStructMutator(const StructDef &struct_def, const FieldDef &field,
const FieldDef &field,
std::string *code_ptr) { std::string *code_ptr) {
GenComment(field.doc_comment, code_ptr, nullptr, ""); GenComment(field.doc_comment, code_ptr, nullptr, "");
if (IsScalar(field.value.type.base_type)) { if (IsScalar(field.value.type.base_type)) {
@@ -601,8 +580,7 @@ static void GenTableBuilders(const StructDef &struct_def,
GetStartOfTable(struct_def, code_ptr); GetStartOfTable(struct_def, code_ptr);
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) continue; if (field.deprecated) continue;
@@ -617,8 +595,7 @@ static void GenTableBuilders(const StructDef &struct_def,
} }
// Generate struct or table methods. // Generate struct or table methods.
static void GenStruct(const StructDef &struct_def, static void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
std::string *code_ptr) {
if (struct_def.generated) return; if (struct_def.generated) return;
GenComment(struct_def.doc_comment, code_ptr, nullptr); GenComment(struct_def.doc_comment, code_ptr, nullptr);
@@ -636,8 +613,7 @@ static void GenStruct(const StructDef &struct_def,
// Generate struct fields accessors // Generate struct fields accessors
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) continue; if (field.deprecated) continue;
@@ -661,8 +637,7 @@ static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
GenComment(enum_def.doc_comment, code_ptr, nullptr); GenComment(enum_def.doc_comment, code_ptr, nullptr);
BeginEnum(code_ptr); BeginEnum(code_ptr);
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
it != enum_def.vals.vec.end();
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
GenComment(ev.doc_comment, code_ptr, nullptr, "\t"); GenComment(ev.doc_comment, code_ptr, nullptr, "\t");
@@ -671,8 +646,7 @@ static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
EndEnum(code_ptr); EndEnum(code_ptr);
BeginEnumNames(enum_def, code_ptr); BeginEnumNames(enum_def, code_ptr);
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
it != enum_def.vals.vec.end();
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
EnumNameMember(enum_def, ev, code_ptr); EnumNameMember(enum_def, ev, code_ptr);
@@ -686,8 +660,7 @@ static std::string GenGetter(const Type &type) {
case BASE_TYPE_STRING: return "rcv._tab.ByteVector"; case BASE_TYPE_STRING: return "rcv._tab.ByteVector";
case BASE_TYPE_UNION: return "rcv._tab.Union"; case BASE_TYPE_UNION: return "rcv._tab.Union";
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
default: default: return "rcv._tab.Get" + MakeCamel(GenTypeGet(type));
return "rcv._tab.Get" + MakeCamel(GenTypeGet(type));
} }
} }
@@ -700,34 +673,30 @@ static std::string GenMethod(const FieldDef &field) {
static std::string GenTypeBasic(const Type &type) { static std::string GenTypeBasic(const Type &type) {
static const char *ctypename[] = { static const char *ctypename[] = {
// clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#GTYPE, #GTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD #undef FLATBUFFERS_TD
// clang-format on
}; };
return ctypename[type.base_type]; return ctypename[type.base_type];
} }
static std::string GenTypePointer(const Type &type) { static std::string GenTypePointer(const Type &type) {
switch (type.base_type) { switch (type.base_type) {
case BASE_TYPE_STRING: case BASE_TYPE_STRING: return "[]byte";
return "[]byte"; case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
case BASE_TYPE_VECTOR: case BASE_TYPE_STRUCT: return type.struct_def->name;
return GenTypeGet(type.VectorType());
case BASE_TYPE_STRUCT:
return type.struct_def->name;
case BASE_TYPE_UNION: case BASE_TYPE_UNION:
// fall through // fall through
default: default: return "*flatbuffers.Table";
return "*flatbuffers.Table";
} }
} }
static std::string GenTypeGet(const Type &type) { static std::string GenTypeGet(const Type &type) {
return IsScalar(type.base_type) return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
? GenTypeBasic(type)
: GenTypePointer(type);
} }
static std::string TypeName(const FieldDef &field) { static std::string TypeName(const FieldDef &field) {
@@ -749,7 +718,8 @@ class GoGenerator : public BaseGenerator {
public: public:
GoGenerator(const Parser &parser, const std::string &path, GoGenerator(const Parser &parser, const std::string &path,
const std::string &file_name, const std::string &go_namespace) const std::string &file_name, const std::string &go_namespace)
: BaseGenerator(parser, path, file_name, "" /* not used*/, "" /* not used */) { : BaseGenerator(parser, path, file_name, "" /* not used*/,
"" /* not used */) {
std::istringstream iss(go_namespace); std::istringstream iss(go_namespace);
std::string component; std::string component;
while (std::getline(iss, component, '.')) { while (std::getline(iss, component, '.')) {
@@ -815,12 +785,12 @@ class GoGenerator : public BaseGenerator {
bool needs_imports) { bool needs_imports) {
if (!classcode.length()) return true; if (!classcode.length()) return true;
Namespace& ns = go_namespace_.components.empty() ? *def.defined_namespace : go_namespace_; Namespace &ns = go_namespace_.components.empty() ? *def.defined_namespace
: go_namespace_;
std::string code = ""; std::string code = "";
BeginFile(LastNamespacePart(ns), needs_imports, &code); BeginFile(LastNamespacePart(ns), needs_imports, &code);
code += classcode; code += classcode;
std::string filename = std::string filename = NamespaceDir(ns) + def.name + ".go";
NamespaceDir(ns) + def.name + ".go";
return SaveFile(filename.c_str(), code, false); return SaveFile(filename.c_str(), code, false);
} }

View File

@@ -16,10 +16,10 @@
// independent from idl_parser, since this code is not needed for most clients // independent from idl_parser, since this code is not needed for most clients
#include "flatbuffers/code_generators.h"
#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 "flatbuffers/code_generators.h"
#include "src/compiler/cpp_generator.h" #include "src/compiler/cpp_generator.h"
#include "src/compiler/go_generator.h" #include "src/compiler/go_generator.h"
@@ -27,7 +27,8 @@
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning(push) # pragma warning(push)
#pragma warning(disable: 4512) // C4512: 'class' : assignment operator could not be generated # pragma warning(disable : 4512) // C4512: 'class' : assignment operator could
// not be generated
#endif #endif
namespace flatbuffers { namespace flatbuffers {
@@ -36,8 +37,7 @@ class FlatBufMethod : public grpc_generator::Method {
public: public:
enum Streaming { kNone, kClient, kServer, kBiDi }; enum Streaming { kNone, kClient, kServer, kBiDi };
FlatBufMethod(const RPCCall *method) FlatBufMethod(const RPCCall *method) : method_(method) {
: method_(method) {
streaming_ = kNone; streaming_ = kNone;
auto val = method_->attributes.Lookup("streaming"); auto val = method_->attributes.Lookup("streaming");
if (val) { if (val) {
@@ -47,12 +47,8 @@ class FlatBufMethod : public grpc_generator::Method {
} }
} }
grpc::string GetLeadingComments(const grpc::string) const { grpc::string GetLeadingComments(const grpc::string) const { return ""; }
return ""; grpc::string GetTrailingComments(const grpc::string) const { return ""; }
}
grpc::string GetTrailingComments(const grpc::string) const {
return "";
}
std::vector<grpc::string> GetAllComments() const { std::vector<grpc::string> GetAllComments() const {
return method_->rpc_comment; return method_->rpc_comment;
} }
@@ -63,16 +59,13 @@ class FlatBufMethod : public grpc_generator::Method {
return "flatbuffers::grpc::Message<" + sd.name + ">"; return "flatbuffers::grpc::Message<" + sd.name + ">";
} }
std::string get_input_type_name() const { std::string get_input_type_name() const { return (*method_->request).name; }
return (*method_->request).name; std::string get_output_type_name() const { return (*method_->response).name; }
}
std::string get_output_type_name() const {
return (*method_->response).name;
}
bool get_module_and_message_path_input( bool get_module_and_message_path_input(grpc::string * /*str*/,
grpc::string * /*str*/, grpc::string /*generator_file_name*/, grpc::string /*generator_file_name*/,
bool /*generate_in_pb2_grpc*/, grpc::string /*import_prefix*/) const { bool /*generate_in_pb2_grpc*/,
grpc::string /*import_prefix*/) const {
return true; return true;
} }
@@ -82,13 +75,9 @@ class FlatBufMethod : public grpc_generator::Method {
return true; return true;
} }
std::string input_type_name() const { std::string input_type_name() const { return GRPCType(*method_->request); }
return GRPCType(*method_->request);
}
std::string output_type_name() const { std::string output_type_name() const { return GRPCType(*method_->response); }
return GRPCType(*method_->response);
}
bool NoStreaming() const { return streaming_ == kNone; } bool NoStreaming() const { return streaming_ == kNone; }
bool ClientStreaming() const { return streaming_ == kClient; } bool ClientStreaming() const { return streaming_ == kClient; }
@@ -104,12 +93,8 @@ class FlatBufService : public grpc_generator::Service {
public: public:
FlatBufService(const ServiceDef *service) : service_(service) {} FlatBufService(const ServiceDef *service) : service_(service) {}
grpc::string GetLeadingComments(const grpc::string) const { grpc::string GetLeadingComments(const grpc::string) const { return ""; }
return ""; grpc::string GetTrailingComments(const grpc::string) const { return ""; }
}
grpc::string GetTrailingComments(const grpc::string) const {
return "";
}
std::vector<grpc::string> GetAllComments() const { std::vector<grpc::string> GetAllComments() const {
return service_->doc_comment; return service_->doc_comment;
} }
@@ -131,8 +116,7 @@ class FlatBufService : public grpc_generator::Service {
class FlatBufPrinter : public grpc_generator::Printer { class FlatBufPrinter : public grpc_generator::Printer {
public: public:
FlatBufPrinter(std::string *str) FlatBufPrinter(std::string *str) : str_(str), escape_char_('$'), indent_(0) {}
: str_(str), escape_char_('$'), indent_(0) {}
void Print(const std::map<std::string, std::string> &vars, void Print(const std::map<std::string, std::string> &vars,
const char *string_template) { const char *string_template) {
@@ -155,9 +139,7 @@ class FlatBufPrinter : public grpc_generator::Printer {
} }
void Print(const char *s) { void Print(const char *s) {
if (s == nullptr || std::strlen(s) == 0) { if (s == nullptr || std::strlen(s) == 0) { return; }
return;
}
// Add this string, but for each part separated by \n, add indentation. // Add this string, but for each part separated by \n, add indentation.
for (;;) { for (;;) {
// Current indentation. // Current indentation.
@@ -176,7 +158,10 @@ class FlatBufPrinter : public grpc_generator::Printer {
} }
void Indent() { indent_++; } void Indent() { indent_++; }
void Outdent() { indent_--; assert(indent_ >= 0); } void Outdent() {
indent_--;
assert(indent_ >= 0);
}
private: private:
std::string *str_; std::string *str_;
@@ -186,23 +171,15 @@ class FlatBufPrinter : public grpc_generator::Printer {
class FlatBufFile : public grpc_generator::File { class FlatBufFile : public grpc_generator::File {
public: public:
enum Language { enum Language { kLanguageGo, kLanguageCpp, kLanguageJava };
kLanguageGo,
kLanguageCpp,
kLanguageJava
};
FlatBufFile( FlatBufFile(const Parser &parser, const std::string &file_name,
const Parser &parser, const std::string &file_name, Language language) Language language)
: parser_(parser), file_name_(file_name), language_(language) {} : parser_(parser), file_name_(file_name), language_(language) {}
FlatBufFile &operator=(const FlatBufFile &); FlatBufFile &operator=(const FlatBufFile &);
grpc::string GetLeadingComments(const grpc::string) const { grpc::string GetLeadingComments(const grpc::string) const { return ""; }
return ""; grpc::string GetTrailingComments(const grpc::string) const { return ""; }
}
grpc::string GetTrailingComments(const grpc::string) const {
return "";
}
std::vector<grpc::string> GetAllComments() const { std::vector<grpc::string> GetAllComments() const {
return std::vector<grpc::string>(); return std::vector<grpc::string>();
} }
@@ -247,9 +224,9 @@ class FlatBufFile : public grpc_generator::File {
new FlatBufService(parser_.services_.vec[i])); new FlatBufService(parser_.services_.vec[i]));
} }
std::unique_ptr<grpc_generator::Printer> CreatePrinter(std::string *str) const { std::unique_ptr<grpc_generator::Printer> CreatePrinter(
return std::unique_ptr<grpc_generator::Printer>( std::string *str) const {
new FlatBufPrinter(str)); return std::unique_ptr<grpc_generator::Printer>(new FlatBufPrinter(str));
} }
private: private:
@@ -263,7 +240,9 @@ class GoGRPCGenerator : public flatbuffers::BaseGenerator {
GoGRPCGenerator(const Parser &parser, const std::string &path, GoGRPCGenerator(const Parser &parser, const std::string &path,
const std::string &file_name) const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "" /*Unused*/), : BaseGenerator(parser, path, file_name, "", "" /*Unused*/),
parser_(parser), path_(path), file_name_(file_name) {} parser_(parser),
path_(path),
file_name_(file_name) {}
bool generate() { bool generate() {
FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageGo); FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageGo);
@@ -273,10 +252,11 @@ class GoGRPCGenerator : public flatbuffers::BaseGenerator {
auto service = file.service(i); auto service = file.service(i);
const Definition *def = parser_.services_.vec[i]; const Definition *def = parser_.services_.vec[i];
p.package_name = LastNamespacePart(*(def->defined_namespace)); p.package_name = LastNamespacePart(*(def->defined_namespace));
std::string output = grpc_go_generator::GenerateServiceSource(&file, service.get(), &p); std::string output =
std::string filename = NamespaceDir(*def->defined_namespace) + def->name + "_grpc.go"; grpc_go_generator::GenerateServiceSource(&file, service.get(), &p);
if (!flatbuffers::SaveFile(filename.c_str(), output, false)) std::string filename =
return false; NamespaceDir(*def->defined_namespace) + def->name + "_grpc.go";
if (!flatbuffers::SaveFile(filename.c_str(), output, false)) return false;
} }
return true; return true;
} }
@@ -286,25 +266,22 @@ class GoGRPCGenerator : public flatbuffers::BaseGenerator {
const std::string &path_, &file_name_; const std::string &path_, &file_name_;
}; };
bool GenerateGoGRPC(const Parser &parser, bool GenerateGoGRPC(const Parser &parser, const std::string &path,
const std::string &path,
const std::string &file_name) { const std::string &file_name) {
int nservices = 0; int nservices = 0;
for (auto it = parser.services_.vec.begin(); for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
it != parser.services_.vec.end(); ++it) { ++it) {
if (!(*it)->generated) nservices++; if (!(*it)->generated) nservices++;
} }
if (!nservices) return true; if (!nservices) return true;
return GoGRPCGenerator(parser, path, file_name).generate(); return GoGRPCGenerator(parser, path, file_name).generate();
} }
bool GenerateCppGRPC(const Parser &parser, bool GenerateCppGRPC(const Parser &parser, const std::string &path,
const std::string &path,
const std::string &file_name) { const std::string &file_name) {
int nservices = 0; int nservices = 0;
for (auto it = parser.services_.vec.begin(); for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
it != parser.services_.vec.end(); ++it) { ++it) {
if (!(*it)->generated) nservices++; if (!(*it)->generated) nservices++;
} }
if (!nservices) return true; if (!nservices) return true;

View File

@@ -15,14 +15,14 @@
*/ */
// independent from idl_parser, since this code is not needed for most clients // independent from idl_parser, since this code is not needed for most clients
#include <unordered_set>
#include <unordered_map>
#include <cassert> #include <cassert>
#include <unordered_map>
#include <unordered_set>
#include "flatbuffers/code_generators.h"
#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 "flatbuffers/code_generators.h"
namespace flatbuffers { namespace flatbuffers {
@@ -77,9 +77,7 @@ class JsGenerator : public BaseGenerator {
JsGenerator(const Parser &parser, const std::string &path, JsGenerator(const Parser &parser, const std::string &path,
const std::string &file_name) const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "."), : BaseGenerator(parser, path, file_name, "", "."),
lang_(GetJsLangParams(parser_.opts.lang)) lang_(GetJsLangParams(parser_.opts.lang)){};
{
};
// Iterate through all definitions we haven't generate code for (enums, // Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file. // structs, and tables) and output them to a single file.
bool generate() { bool generate() {
@@ -133,8 +131,7 @@ class JsGenerator : public BaseGenerator {
// Generate reexports, which might not have been explicitly imported using the // Generate reexports, which might not have been explicitly imported using the
// "export import" trick // "export import" trick
void generateReexports(std::string *code_ptr, void generateReexports(std::string *code_ptr, const reexport_map &reexports,
const reexport_map &reexports,
imported_fileset imported_files) { imported_fileset imported_files) {
if (!parser_.opts.reexport_ts_modules || if (!parser_.opts.reexport_ts_modules ||
lang_.language != IDLOptions::kTs) { lang_.language != IDLOptions::kTs) {
@@ -164,8 +161,7 @@ class JsGenerator : public BaseGenerator {
} }
// Generate code for all enums. // Generate code for all enums.
void generateEnums(std::string *enum_code_ptr, void generateEnums(std::string *enum_code_ptr, std::string *exports_code_ptr,
std::string *exports_code_ptr,
reexport_map &reexports) { reexport_map &reexports) {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) { ++it) {
@@ -193,31 +189,29 @@ class JsGenerator : public BaseGenerator {
std::set<std::string> namespaces; std::set<std::string> namespaces;
for (auto it = parser_.namespaces_.begin(); for (auto it = parser_.namespaces_.begin(); it != parser_.namespaces_.end();
it != parser_.namespaces_.end(); ++it) { ++it) {
std::string namespace_so_far; std::string namespace_so_far;
// Gather all parent namespaces for this namespace // Gather all parent namespaces for this namespace
for (auto component = (*it)->components.begin(); for (auto component = (*it)->components.begin();
component != (*it)->components.end(); ++component) { component != (*it)->components.end(); ++component) {
if (!namespace_so_far.empty()) { if (!namespace_so_far.empty()) { namespace_so_far += '.'; }
namespace_so_far += '.';
}
namespace_so_far += *component; namespace_so_far += *component;
namespaces.insert(namespace_so_far); namespaces.insert(namespace_so_far);
} }
} }
// Make sure parent namespaces come before child namespaces // Make sure parent namespaces come before child namespaces
std::vector<std::string> sorted_namespaces( std::vector<std::string> sorted_namespaces(namespaces.begin(),
namespaces.begin(), namespaces.end()); namespaces.end());
std::sort(sorted_namespaces.begin(), sorted_namespaces.end()); std::sort(sorted_namespaces.begin(), sorted_namespaces.end());
// Emit namespaces in a form that Closure Compiler can optimize // Emit namespaces in a form that Closure Compiler can optimize
std::string &code = *code_ptr; std::string &code = *code_ptr;
std::string &exports = *exports_ptr; std::string &exports = *exports_ptr;
for (auto it = sorted_namespaces.begin(); for (auto it = sorted_namespaces.begin(); it != sorted_namespaces.end();
it != sorted_namespaces.end(); it++) { it++) {
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
if (it->find('.') == std::string::npos) { if (it->find('.') == std::string::npos) {
code += "import { flatbuffers } from \"./flatbuffers\"\n"; code += "import { flatbuffers } from \"./flatbuffers\"\n";
@@ -291,9 +285,7 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
GenDocComment(enum_def.doc_comment, code_ptr, "@enum"); GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
std::string ns = GetNameSpace(enum_def); std::string ns = GetNameSpace(enum_def);
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
if (!ns.empty()) { if (!ns.empty()) { code += "export namespace " + ns + "{\n"; }
code += "export namespace " + ns + "{\n";
}
code += "export enum " + enum_def.name + "{\n"; code += "export enum " + enum_def.name + "{\n";
} else { } else {
if (enum_def.defined_namespace->components.empty()) { if (enum_def.defined_namespace->components.empty()) {
@@ -307,13 +299,11 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
} }
code += WrapInNameSpace(enum_def) + " = {\n"; code += WrapInNameSpace(enum_def) + " = {\n";
} }
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
it != enum_def.vals.vec.end(); ++it) { ++it) {
auto &ev = **it; auto &ev = **it;
if (!ev.doc_comment.empty()) { if (!ev.doc_comment.empty()) {
if (it != enum_def.vals.vec.begin()) { if (it != enum_def.vals.vec.begin()) { code += '\n'; }
code += '\n';
}
GenDocComment(ev.doc_comment, code_ptr, "", " "); GenDocComment(ev.doc_comment, code_ptr, "", " ");
} }
code += " " + ev.name; code += " " + ev.name;
@@ -322,19 +312,15 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n"; code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n";
if (ev.union_type.struct_def) { if (ev.union_type.struct_def) {
ReexportDescription desc = { ReexportDescription desc = { ev.name,
ev.name,
GetNameSpace(*ev.union_type.struct_def), GetNameSpace(*ev.union_type.struct_def),
GetNameSpace(enum_def) GetNameSpace(enum_def) };
}; reexports.insert(
reexports.insert(std::make_pair(ev.union_type.struct_def->file, std::make_pair(ev.union_type.struct_def->file, std::move(desc)));
std::move(desc)));
} }
} }
if (lang_.language == IDLOptions::kTs && !ns.empty()) { if (lang_.language == IDLOptions::kTs && !ns.empty()) { code += "}"; }
code += "}";
}
code += "};\n\n"; code += "};\n\n";
} }
@@ -366,10 +352,9 @@ std::string GenGetter(const Type &type, const std::string &arguments) {
case BASE_TYPE_UNION: return GenBBAccess() + ".__union" + arguments; case BASE_TYPE_UNION: return GenBBAccess() + ".__union" + arguments;
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType(), arguments); case BASE_TYPE_VECTOR: return GenGetter(type.VectorType(), arguments);
default: { default: {
auto getter = GenBBAccess() + ".read" + MakeCamel(GenType(type)) + arguments; auto getter =
if (type.base_type == BASE_TYPE_BOOL) { GenBBAccess() + ".read" + MakeCamel(GenType(type)) + arguments;
getter = "!!" + getter; if (type.base_type == BASE_TYPE_BOOL) { getter = "!!" + getter; }
}
if (type.enum_def) { if (type.enum_def) {
getter = "/** @type {" + WrapInNameSpace(*type.enum_def) + "} */ (" + getter = "/** @type {" + WrapInNameSpace(*type.enum_def) + "} */ (" +
getter + ")"; getter + ")";
@@ -389,22 +374,21 @@ std::string GenDefaultValue(const Value &value, const std::string &context) {
atoi(value.constant.c_str()), false)) { atoi(value.constant.c_str()), false)) {
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
return GenPrefixedTypeName(WrapInNameSpace(*value.type.enum_def), return GenPrefixedTypeName(WrapInNameSpace(*value.type.enum_def),
value.type.enum_def->file) + "." + val->name; value.type.enum_def->file) +
"." + val->name;
} else { } else {
return WrapInNameSpace(*value.type.enum_def) + "." + val->name; return WrapInNameSpace(*value.type.enum_def) + "." + val->name;
} }
} else { } else {
return "/** @type {" + WrapInNameSpace(*value.type.enum_def) + "} */ (" return "/** @type {" + WrapInNameSpace(*value.type.enum_def) +
+ value.constant + ")"; "} */ (" + value.constant + ")";
} }
} }
switch (value.type.base_type) { switch (value.type.base_type) {
case BASE_TYPE_BOOL: case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true";
return value.constant == "0" ? "false" : "true";
case BASE_TYPE_STRING: case BASE_TYPE_STRING: return "null";
return "null";
case BASE_TYPE_LONG: case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: { case BASE_TYPE_ULONG: {
@@ -413,14 +397,15 @@ std::string GenDefaultValue(const Value &value, const std::string &context) {
", " + NumToString((int32_t)(constant >> 32)) + ")"; ", " + NumToString((int32_t)(constant >> 32)) + ")";
} }
default: default: return value.constant;
return value.constant;
} }
} }
std::string GenTypeName(const Type &type, bool input, bool allowNull = false) { std::string GenTypeName(const Type &type, bool input,
bool allowNull = false) {
if (!input) { if (!input) {
if (type.base_type == BASE_TYPE_STRING || type.base_type == BASE_TYPE_STRUCT) { if (type.base_type == BASE_TYPE_STRING ||
type.base_type == BASE_TYPE_STRUCT) {
std::string name; std::string name;
if (type.base_type == BASE_TYPE_STRING) { if (type.base_type == BASE_TYPE_STRING) {
name = "string|Uint8Array"; name = "string|Uint8Array";
@@ -437,9 +422,7 @@ std::string GenTypeName(const Type &type, bool input, bool allowNull = false) {
case BASE_TYPE_ULONG: return "flatbuffers.Long"; case BASE_TYPE_ULONG: return "flatbuffers.Long";
default: default:
if (IsScalar(type.base_type)) { if (IsScalar(type.base_type)) {
if (type.enum_def) { if (type.enum_def) { return WrapInNameSpace(*type.enum_def); }
return WrapInNameSpace(*type.enum_def);
}
return "number"; return "number";
} }
return "flatbuffers.Offset"; return "flatbuffers.Offset";
@@ -458,24 +441,21 @@ static std::string GenWriteMethod(const Type &type) {
default: break; default: break;
} }
return IsScalar(type.base_type) return IsScalar(type.base_type) ? MakeCamel(GenType(type))
? MakeCamel(GenType(type))
: (IsStruct(type) ? "Struct" : "Offset"); : (IsStruct(type) ? "Struct" : "Offset");
} }
template <typename T> template<typename T> static std::string MaybeAdd(T value) {
static std::string MaybeAdd(T value) {
return value != 0 ? " + " + NumToString(value) : ""; return value != 0 ? " + " + NumToString(value) : "";
} }
template <typename T> template<typename T> static std::string MaybeScale(T value) {
static std::string MaybeScale(T value) {
return value != 1 ? " * " + NumToString(value) : ""; return value != 1 ? " * " + NumToString(value) : "";
} }
static std::string GenFileNamespacePrefix(const std::string &file) { static std::string GenFileNamespacePrefix(const std::string &file) {
return "NS" + std::to_string( return "NS" + std::to_string(static_cast<unsigned long long>(
static_cast<unsigned long long>(std::hash<std::string>()(file))); std::hash<std::string>()(file)));
} }
static std::string GenPrefixedImport(const std::string &full_file_name, static std::string GenPrefixedImport(const std::string &full_file_name,
@@ -489,16 +469,12 @@ std::string GenPrefixedTypeName(const std::string &typeName,
const std::string &file) { const std::string &file) {
const auto basename = const auto basename =
flatbuffers::StripPath(flatbuffers::StripExtension(file)); flatbuffers::StripPath(flatbuffers::StripExtension(file));
if (basename == file_name_) { if (basename == file_name_) { return typeName; }
return typeName;
}
return GenFileNamespacePrefix(file) + "." + typeName; return GenFileNamespacePrefix(file) + "." + typeName;
} }
void GenStructArgs(const StructDef &struct_def, void GenStructArgs(const StructDef &struct_def, std::string *annotations,
std::string *annotations, std::string *arguments, const std::string &nameprefix) {
std::string *arguments,
const std::string &nameprefix) {
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
auto &field = **it; auto &field = **it;
@@ -522,8 +498,7 @@ void GenStructArgs(const StructDef &struct_def,
} }
} }
static void GenStructBody(const StructDef &struct_def, static void GenStructBody(const StructDef &struct_def, std::string *body,
std::string *body,
const std::string &nameprefix) { const std::string &nameprefix) {
*body += " builder.prep("; *body += " builder.prep(";
*body += NumToString(struct_def.minalign) + ", "; *body += NumToString(struct_def.minalign) + ", ";
@@ -543,9 +518,7 @@ static void GenStructBody(const StructDef &struct_def,
nameprefix + field.name + "_"); nameprefix + field.name + "_");
} else { } else {
*body += " builder.write" + GenWriteMethod(field.value.type) + "("; *body += " builder.write" + GenWriteMethod(field.value.type) + "(";
if (field.value.type.base_type == BASE_TYPE_BOOL) { if (field.value.type.base_type == BASE_TYPE_BOOL) { *body += "+"; }
*body += "+";
}
*body += nameprefix + field.name + ");\n"; *body += nameprefix + field.name + ");\n";
} }
} }
@@ -589,7 +562,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
exports += "goog.exportSymbol('" + struct_def.name + "', " + exports += "goog.exportSymbol('" + struct_def.name + "', " +
struct_def.name + ");\n"; struct_def.name + ");\n";
} else { } else {
exports += "this." + struct_def.name + " = " + struct_def.name + ";\n"; exports +=
"this." + struct_def.name + " = " + struct_def.name + ";\n";
} }
code += "function " + object_name; code += "function " + object_name;
} else { } else {
@@ -617,8 +591,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
code += " */\n"; code += " */\n";
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + code +=
" {\n"; "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + " {\n";
} else { } else {
code += object_name + ".prototype.__init = function(i, bb) {\n"; code += object_name + ".prototype.__init = function(i, bb) {\n";
} }
@@ -633,12 +607,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
if (!struct_def.fixed) { if (!struct_def.fixed) {
GenDocComment(code_ptr, GenDocComment(code_ptr,
"@param {flatbuffers.ByteBuffer} bb\n" "@param {flatbuffers.ByteBuffer} bb\n"
"@param {" + object_name + "=} obj\n" "@param {" +
"@returns {" + object_name + "}"); object_name +
"=} obj\n"
"@returns {" +
object_name + "}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "static getRootAs" + struct_def.name; code += "static getRootAs" + struct_def.name;
code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name + "):" + code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name +
object_name + " {\n"; "):" + object_name + " {\n";
} else { } else {
code += object_name + ".getRootAs" + struct_def.name; code += object_name + ".getRootAs" + struct_def.name;
code += " = function(bb, obj) {\n"; code += " = function(bb, obj) {\n";
@@ -655,7 +632,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
"@returns {boolean}"); "@returns {boolean}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += code +=
"static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean {\n"; "static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean "
"{\n";
} else { } else {
code += object_name + ".bufferHasIdentifier = function(bb) {\n"; code += object_name + ".bufferHasIdentifier = function(bb) {\n";
} }
@@ -670,31 +648,37 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
auto &field = **it; auto &field = **it;
if (field.deprecated) continue; if (field.deprecated) continue;
auto offset_prefix = " var offset = " + GenBBAccess() + auto offset_prefix =
".__offset(this.bb_pos, " + NumToString(field.value.offset) + " var offset = " + GenBBAccess() + ".__offset(this.bb_pos, " +
");\n return offset ? "; NumToString(field.value.offset) + ");\n return offset ? ";
// Emit a scalar field // Emit a scalar field
if (IsScalar(field.value.type.base_type) || if (IsScalar(field.value.type.base_type) ||
field.value.type.base_type == BASE_TYPE_STRING) { field.value.type.base_type == BASE_TYPE_STRING) {
GenDocComment(field.doc_comment, code_ptr, GenDocComment(
std::string(field.value.type.base_type == BASE_TYPE_STRING ? field.doc_comment, code_ptr,
"@param {flatbuffers.Encoding=} optionalEncoding\n" : "") + std::string(
"@returns {" + GenTypeName(field.value.type, false, true) + "}"); field.value.type.base_type == BASE_TYPE_STRING
? "@param {flatbuffers.Encoding=} optionalEncoding\n"
: "") +
"@returns {" + GenTypeName(field.value.type, false, true) +
"}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
std::string prefix = MakeCamel(field.name, false) + "("; std::string prefix = MakeCamel(field.name, false) + "(";
if (field.value.type.base_type == BASE_TYPE_STRING) { if (field.value.type.base_type == BASE_TYPE_STRING) {
code += prefix + "):string|null\n"; code += prefix + "):string|null\n";
code += prefix + "optionalEncoding:flatbuffers.Encoding"+"):" + code += prefix + "optionalEncoding:flatbuffers.Encoding" +
GenTypeName(field.value.type, false, true)+"\n"; "):" + GenTypeName(field.value.type, false, true) + "\n";
code += prefix + "optionalEncoding?:any"; code += prefix + "optionalEncoding?:any";
} else { } else {
code += prefix; code += prefix;
} }
if (field.value.type.enum_def) { if (field.value.type.enum_def) {
code += "):" + code +=
"):" +
GenPrefixedTypeName(GenTypeName(field.value.type, false, true), GenPrefixedTypeName(GenTypeName(field.value.type, false, true),
field.value.type.enum_def->file) + " {\n"; field.value.type.enum_def->file) +
" {\n";
} else { } else {
code += "):" + GenTypeName(field.value.type, false, true) + " {\n"; code += "):" + GenTypeName(field.value.type, false, true) + " {\n";
} }
@@ -708,15 +692,19 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
} }
if (struct_def.fixed) { if (struct_def.fixed) {
code += " return " + GenGetter(field.value.type, "(this.bb_pos" + code +=
MaybeAdd(field.value.offset) + ")") + ";\n"; " return " +
GenGetter(field.value.type,
"(this.bb_pos" + MaybeAdd(field.value.offset) + ")") +
";\n";
} else { } else {
std::string index = "this.bb_pos + offset"; std::string index = "this.bb_pos + offset";
if (field.value.type.base_type == BASE_TYPE_STRING) { if (field.value.type.base_type == BASE_TYPE_STRING) {
index += ", optionalEncoding"; index += ", optionalEncoding";
} }
code += offset_prefix + GenGetter(field.value.type, code += offset_prefix +
"(" + index + ")") + " : " + GenDefaultValue(field.value, GenBBAccess()); GenGetter(field.value.type, "(" + index + ")") + " : " +
GenDefaultValue(field.value, GenBBAccess());
code += ";\n"; code += ";\n";
} }
} }
@@ -726,21 +714,25 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
switch (field.value.type.base_type) { switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: { case BASE_TYPE_STRUCT: {
auto type = WrapInNameSpace(*field.value.type.struct_def); auto type = WrapInNameSpace(*field.value.type.struct_def);
GenDocComment(field.doc_comment, code_ptr, GenDocComment(
field.doc_comment, code_ptr,
"@param {" + type + "=} obj\n@returns {" + type + "|null}"); "@param {" + type + "=} obj\n@returns {" + type + "|null}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
type = GenPrefixedTypeName(type, field.value.type.struct_def->file); type =
GenPrefixedTypeName(type, field.value.type.struct_def->file);
code += MakeCamel(field.name, false); code += MakeCamel(field.name, false);
code += "(obj?:" + type + "):" + type + "|null {\n"; code += "(obj?:" + type + "):" + type + "|null {\n";
} else { } else {
code += object_name + ".prototype." + MakeCamel(field.name, false); code +=
object_name + ".prototype." + MakeCamel(field.name, false);
code += " = function(obj) {\n"; code += " = function(obj) {\n";
} }
if (struct_def.fixed) { if (struct_def.fixed) {
code += " return (obj || new " + type; code += " return (obj || new " + type;
code += ").__init(this.bb_pos"; code += ").__init(this.bb_pos";
code += MaybeAdd(field.value.offset) + ", " + GenBBAccess() + ");\n"; code +=
MaybeAdd(field.value.offset) + ", " + GenBBAccess() + ");\n";
} else { } else {
code += offset_prefix + "(obj || new " + type + ").__init("; code += offset_prefix + "(obj || new " + type + ").__init(";
code += field.value.type.struct_def->fixed code += field.value.type.struct_def->fixed
@@ -760,7 +752,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
auto vectortype = field.value.type.VectorType(); auto vectortype = field.value.type.VectorType();
auto vectortypename = GenTypeName(vectortype, false); auto vectortypename = GenTypeName(vectortype, false);
auto inline_size = InlineSize(vectortype); auto inline_size = InlineSize(vectortype);
auto index = GenBBAccess() + ".__vector(this.bb_pos + offset) + index" + auto index = GenBBAccess() +
".__vector(this.bb_pos + offset) + index" +
MaybeScale(inline_size); MaybeScale(inline_size);
std::string args = "@param {number} index\n"; std::string args = "@param {number} index\n";
std::string ret_type; std::string ret_type;
@@ -779,36 +772,34 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
ret_type = "?flatbuffers.Table"; ret_type = "?flatbuffers.Table";
is_union = true; is_union = true;
break; break;
default: default: ret_type = vectortypename;
ret_type = vectortypename;
} }
GenDocComment(field.doc_comment, code_ptr, args + GenDocComment(field.doc_comment, code_ptr,
"@returns {" + ret_type + "}"); args + "@returns {" + ret_type + "}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
std::string prefix = MakeCamel(field.name, false); std::string prefix = MakeCamel(field.name, false);
if (is_union) { if (is_union) { prefix += "<T extends flatbuffers.Table>"; }
prefix += "<T extends flatbuffers.Table>";
}
prefix += "(index: number"; prefix += "(index: number";
if (is_union) { if (is_union) {
vectortypename = "T"; vectortypename = "T";
code += prefix + ", obj:T"; code += prefix + ", obj:T";
} else if (vectortype.base_type == BASE_TYPE_STRUCT) { } else if (vectortype.base_type == BASE_TYPE_STRUCT) {
vectortypename = GenPrefixedTypeName(vectortypename, vectortypename = GenPrefixedTypeName(
vectortype.struct_def->file); vectortypename, vectortype.struct_def->file);
code += prefix + ", obj?:" + vectortypename; code += prefix + ", obj?:" + vectortypename;
imported_files.insert(vectortype.struct_def->file); imported_files.insert(vectortype.struct_def->file);
} else if (vectortype.base_type == BASE_TYPE_STRING) { } else if (vectortype.base_type == BASE_TYPE_STRING) {
code += prefix + "):string\n"; code += prefix + "):string\n";
code += prefix + ",optionalEncoding:flatbuffers.Encoding" + "):" + code += prefix + ",optionalEncoding:flatbuffers.Encoding" +
vectortypename + "\n"; "):" + vectortypename + "\n";
code += prefix + ",optionalEncoding?:any"; code += prefix + ",optionalEncoding?:any";
} else { } else {
code += prefix; code += prefix;
} }
code += "):" + vectortypename + "|null {\n"; code += "):" + vectortypename + "|null {\n";
} else { } else {
code += object_name + ".prototype." + MakeCamel(field.name, false); code +=
object_name + ".prototype." + MakeCamel(field.name, false);
code += " = function(index"; code += " = function(index";
if (vectortype.base_type == BASE_TYPE_STRUCT || is_union) { if (vectortype.base_type == BASE_TYPE_STRUCT || is_union) {
code += ", obj"; code += ", obj";
@@ -862,32 +853,32 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
code += MakeCamel(field.name, false); code += MakeCamel(field.name, false);
code += "<T extends flatbuffers.Table>(obj:T):T|null {\n"; code += "<T extends flatbuffers.Table>(obj:T):T|null {\n";
} else { } else {
code += object_name + ".prototype." + MakeCamel(field.name, false); code +=
object_name + ".prototype." + MakeCamel(field.name, false);
code += " = function(obj) {\n"; code += " = function(obj) {\n";
} }
code += offset_prefix + GenGetter(field.value.type, code += offset_prefix +
"(obj, this.bb_pos + offset)") + " : null;\n"; GenGetter(field.value.type, "(obj, this.bb_pos + offset)") +
" : null;\n";
break; break;
default: default: assert(0);
assert(0);
} }
} }
code += "};\n\n"; code += "};\n\n";
if (parser_.opts.use_goog_js_export_format) { if (parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name + ".prototype, '" + exports += "goog.exportProperty(" + object_name + ".prototype, '" +
MakeCamel(field.name, false) + "', " + object_name + ".prototype." + MakeCamel(field.name, false) + "', " + object_name +
MakeCamel(field.name, false) + ");\n"; ".prototype." + MakeCamel(field.name, false) + ");\n";
} }
// Adds the mutable scalar value to the output // Adds the mutable scalar value to the output
if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer) { if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer) {
std::string annotations = std::string annotations =
"@param {" + GenTypeName(field.value.type, true) + "} value\n"; "@param {" + GenTypeName(field.value.type, true) + "} value\n";
GenDocComment(code_ptr, annotations + GenDocComment(code_ptr, annotations + "@returns {boolean}");
"@returns {boolean}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
std::string type; std::string type;
@@ -912,7 +903,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
// special case for bools, which are treated as uint8 // special case for bools, which are treated as uint8
code += " " + GenBBAccess() + ".write" + code += " " + GenBBAccess() + ".write" +
MakeCamel(GenType(field.value.type)) + "(this.bb_pos + offset, "; MakeCamel(GenType(field.value.type)) +
"(this.bb_pos + offset, ";
if (field.value.type.base_type == BASE_TYPE_BOOL && if (field.value.type.base_type == BASE_TYPE_BOOL &&
lang_.language == IDLOptions::kTs) { lang_.language == IDLOptions::kTs) {
code += "+"; code += "+";
@@ -941,18 +933,21 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
code += "Length = function() {\n" + offset_prefix; code += "Length = function() {\n" + offset_prefix;
} }
code += GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n};\n\n"; code +=
GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n};\n\n";
if (parser_.opts.use_goog_js_export_format) { if (parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name + ".prototype, '" + exports += "goog.exportProperty(" + object_name + ".prototype, '" +
MakeCamel(field.name, false) + "Length', " + object_name + MakeCamel(field.name, false) + "Length', " + object_name +
".prototype." + MakeCamel(field.name, false) + "Length);\n"; ".prototype." + MakeCamel(field.name, false) +
"Length);\n";
} }
// For scalar types, emit a typed array helper // For scalar types, emit a typed array helper
auto vectorType = field.value.type.VectorType(); auto vectorType = field.value.type.VectorType();
if (IsScalar(vectorType.base_type) && !IsLong(vectorType.base_type)) { if (IsScalar(vectorType.base_type) && !IsLong(vectorType.base_type)) {
GenDocComment(code_ptr, "@returns {" + GenType(vectorType) + "Array}"); GenDocComment(code_ptr,
"@returns {" + GenType(vectorType) + "Array}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += MakeCamel(field.name, false); code += MakeCamel(field.name, false);
@@ -964,14 +959,16 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
} }
code += "new " + GenType(vectorType) + "Array(" + GenBBAccess() + code += "new " + GenType(vectorType) + "Array(" + GenBBAccess() +
".bytes().buffer, " + GenBBAccess() + ".bytes().byteOffset + " + ".bytes().buffer, " + GenBBAccess() +
GenBBAccess() + ".__vector(this.bb_pos + offset), " + ".bytes().byteOffset + " + GenBBAccess() +
GenBBAccess() + ".__vector_len(this.bb_pos + offset)) : null;\n};\n\n"; ".__vector(this.bb_pos + offset), " + GenBBAccess() +
".__vector_len(this.bb_pos + offset)) : null;\n};\n\n";
if (parser_.opts.use_goog_js_export_format) { if (parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name + ".prototype, '" + exports += "goog.exportProperty(" + object_name + ".prototype, '" +
MakeCamel(field.name, false) + "Array', " + object_name + MakeCamel(field.name, false) + "Array', " + object_name +
".prototype." + MakeCamel(field.name, false) + "Array);\n"; ".prototype." + MakeCamel(field.name, false) +
"Array);\n";
} }
} }
} }
@@ -982,14 +979,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
std::string annotations = "@param {flatbuffers.Builder} builder\n"; std::string annotations = "@param {flatbuffers.Builder} builder\n";
std::string arguments; std::string arguments;
GenStructArgs(struct_def, &annotations, &arguments, ""); GenStructArgs(struct_def, &annotations, &arguments, "");
GenDocComment(code_ptr, annotations + GenDocComment(code_ptr, annotations + "@returns {flatbuffers.Offset}");
"@returns {flatbuffers.Offset}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "static create" + struct_def.name + "(builder:flatbuffers.Builder"; code +=
"static create" + struct_def.name + "(builder:flatbuffers.Builder";
code += arguments + "):flatbuffers.Offset {\n"; code += arguments + "):flatbuffers.Offset {\n";
} else { } else {
code += object_name + ".create" + struct_def.name + " = function(builder"; code +=
object_name + ".create" + struct_def.name + " = function(builder";
code += arguments + ") {\n"; code += arguments + ") {\n";
} }
@@ -997,8 +995,7 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
code += " return builder.offset();\n};\n\n"; code += " return builder.offset();\n};\n\n";
} else { } else {
// Generate a method to start building a new object // Generate a method to start building a new object
GenDocComment(code_ptr, GenDocComment(code_ptr, "@param {flatbuffers.Builder} builder");
"@param {flatbuffers.Builder} builder");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "static start" + struct_def.name; code += "static start" + struct_def.name;
@@ -1008,8 +1005,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
code += " = function(builder) {\n"; code += " = function(builder) {\n";
} }
code += " builder.startObject(" + NumToString( code += " builder.startObject(" +
struct_def.fields.vec.size()) + ");\n"; NumToString(struct_def.fields.vec.size()) + ");\n";
code += "};\n\n"; code += "};\n\n";
// Generate a set of static methods that allow table construction // Generate a set of static methods that allow table construction
@@ -1018,15 +1015,13 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
auto &field = **it; auto &field = **it;
if (field.deprecated) continue; if (field.deprecated) continue;
auto argname = MakeCamel(field.name, false); auto argname = MakeCamel(field.name, false);
if (!IsScalar(field.value.type.base_type)) { if (!IsScalar(field.value.type.base_type)) { argname += "Offset"; }
argname += "Offset";
}
// Generate the field insertion method // Generate the field insertion method
GenDocComment(code_ptr, GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder\n" "@param {flatbuffers.Builder} builder\n"
"@param {" + GenTypeName(field.value.type, true) + "} " + "@param {" +
argname); GenTypeName(field.value.type, true) + "} " + argname);
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
std::string argType; std::string argType;
@@ -1047,16 +1042,12 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
code += " builder.addField" + GenWriteMethod(field.value.type) + "("; code += " builder.addField" + GenWriteMethod(field.value.type) + "(";
code += NumToString(it - struct_def.fields.vec.begin()) + ", "; code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
if (field.value.type.base_type == BASE_TYPE_BOOL) { if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; }
code += "+";
}
code += argname + ", "; code += argname + ", ";
if (!IsScalar(field.value.type.base_type)) { if (!IsScalar(field.value.type.base_type)) {
code += "0"; code += "0";
} else { } else {
if (field.value.type.base_type == BASE_TYPE_BOOL) { if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; }
code += "+";
}
code += GenDefaultValue(field.value, "builder"); code += GenDefaultValue(field.value, "builder");
} }
code += ");\n};\n\n"; code += ");\n};\n\n";
@@ -1070,16 +1061,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
if (!IsStruct(vector_type)) { if (!IsStruct(vector_type)) {
GenDocComment(code_ptr, GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder\n" "@param {flatbuffers.Builder} builder\n"
"@param {Array.<" + GenTypeName(vector_type, true) + "@param {Array.<" +
GenTypeName(vector_type, true) +
">} data\n" ">} data\n"
"@returns {flatbuffers.Offset}"); "@returns {flatbuffers.Offset}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "static create" + MakeCamel(field.name); code += "static create" + MakeCamel(field.name);
std::string type = GenTypeName(vector_type, true) + "[]"; std::string type = GenTypeName(vector_type, true) + "[]";
if (type == "number[]") { if (type == "number[]") { type += " | Uint8Array"; }
type += " | Uint8Array";
}
code += "Vector(builder:flatbuffers.Builder, data:" + type + code += "Vector(builder:flatbuffers.Builder, data:" + type +
"):flatbuffers.Offset {\n"; "):flatbuffers.Offset {\n";
} else { } else {
@@ -1091,16 +1081,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
code += ", data.length, " + NumToString(alignment) + ");\n"; code += ", data.length, " + NumToString(alignment) + ");\n";
code += " for (var i = data.length - 1; i >= 0; i--) {\n"; code += " for (var i = data.length - 1; i >= 0; i--) {\n";
code += " builder.add" + GenWriteMethod(vector_type) + "("; code += " builder.add" + GenWriteMethod(vector_type) + "(";
if (vector_type.base_type == BASE_TYPE_BOOL) { if (vector_type.base_type == BASE_TYPE_BOOL) { code += "+"; }
code += "+";
}
code += "data[i]);\n"; code += "data[i]);\n";
code += " }\n"; code += " }\n";
code += " return builder.endVector();\n"; code += " return builder.endVector();\n";
code += "};\n\n"; code += "};\n\n";
} }
// Generate a method to start a vector, data to be added manually after // Generate a method to start a vector, data to be added manually
// after
GenDocComment(code_ptr, GenDocComment(code_ptr,
"@param {flatbuffers.Builder} builder\n" "@param {flatbuffers.Builder} builder\n"
"@param {number} numElems"); "@param {number} numElems");
@@ -1153,7 +1142,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "static finish" + struct_def.name + "Buffer"; code += "static finish" + struct_def.name + "Buffer";
code += "(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {\n"; code +=
"(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {\n";
} else { } else {
code += object_name + ".finish" + struct_def.name + "Buffer"; code += object_name + ".finish" + struct_def.name + "Buffer";
code += " = function(builder, offset) {\n"; code += " = function(builder, offset) {\n";
@@ -1169,9 +1159,7 @@ void GenStruct(const Parser &parser, StructDef &struct_def,
} }
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
if (!object_namespace.empty()) { if (!object_namespace.empty()) { code += "}\n"; }
code += "}\n";
}
code += "}\n"; code += "}\n";
} }
} }
@@ -1184,19 +1172,17 @@ bool GenerateJS(const Parser &parser, const std::string &path,
return generator.generate(); return generator.generate();
} }
std::string JSMakeRule(const Parser &parser, std::string JSMakeRule(const Parser &parser, const std::string &path,
const std::string &path,
const std::string &file_name) { const std::string &file_name) {
assert(parser.opts.lang <= IDLOptions::kMAX); assert(parser.opts.lang <= IDLOptions::kMAX);
const auto &lang = GetJsLangParams(parser.opts.lang); const auto &lang = GetJsLangParams(parser.opts.lang);
std::string filebase = flatbuffers::StripPath( std::string filebase =
flatbuffers::StripExtension(file_name)); flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
std::string make_rule = GeneratedFileName(path, filebase, lang) + ": "; std::string make_rule = GeneratedFileName(path, filebase, lang) + ": ";
auto included_files = parser.GetIncludedFilesRecursive(file_name); auto included_files = parser.GetIncludedFilesRecursive(file_name);
for (auto it = included_files.begin(); for (auto it = included_files.begin(); it != included_files.end(); ++it) {
it != included_files.end(); ++it) {
make_rule += " " + *it; make_rule += " " + *it;
} }
return make_rule; return make_rule;

View File

@@ -14,10 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
#include <iostream>
#include "flatbuffers/code_generators.h" #include "flatbuffers/code_generators.h"
#include "flatbuffers/idl.h" #include "flatbuffers/idl.h"
#include "flatbuffers/util.h" #include "flatbuffers/util.h"
#include <iostream>
namespace flatbuffers { namespace flatbuffers {
@@ -30,8 +30,7 @@ namespace jsons {
std::string GenNativeType(BaseType type) { std::string GenNativeType(BaseType type) {
switch (type) { switch (type) {
case BASE_TYPE_BOOL: case BASE_TYPE_BOOL: return "boolean";
return "boolean";
case BASE_TYPE_CHAR: case BASE_TYPE_CHAR:
case BASE_TYPE_UCHAR: case BASE_TYPE_UCHAR:
case BASE_TYPE_SHORT: case BASE_TYPE_SHORT:
@@ -41,12 +40,9 @@ std::string GenNativeType(BaseType type) {
case BASE_TYPE_LONG: case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: case BASE_TYPE_ULONG:
case BASE_TYPE_FLOAT: case BASE_TYPE_FLOAT:
case BASE_TYPE_DOUBLE: case BASE_TYPE_DOUBLE: return "number";
return "number"; case BASE_TYPE_STRING: return "string";
case BASE_TYPE_STRING: default: return "";
return "string";
default:
return "";
} }
} }
@@ -93,11 +89,10 @@ std::string GenType(const Type &type) {
const auto &union_types = type.enum_def->vals.vec; const auto &union_types = type.enum_def->vals.vec;
for (auto ut = union_types.cbegin(); ut < union_types.cend(); ++ut) { for (auto ut = union_types.cbegin(); ut < union_types.cend(); ++ut) {
auto &union_type = *ut; auto &union_type = *ut;
if (union_type->union_type.base_type == BASE_TYPE_NONE) { if (union_type->union_type.base_type == BASE_TYPE_NONE) { continue; }
continue;
}
if (union_type->union_type.base_type == BASE_TYPE_STRUCT) { if (union_type->union_type.base_type == BASE_TYPE_STRUCT) {
union_type_string.append("{ " + GenTypeRef(union_type->union_type.struct_def) + " }"); union_type_string.append(
"{ " + GenTypeRef(union_type->union_type.struct_def) + " }");
} }
if (union_type != *type.enum_def->vals.vec.rbegin()) { if (union_type != *type.enum_def->vals.vec.rbegin()) {
union_type_string.append(","); union_type_string.append(",");
@@ -106,10 +101,8 @@ std::string GenType(const Type &type) {
union_type_string.append("]"); union_type_string.append("]");
return union_type_string; return union_type_string;
} }
case BASE_TYPE_UTYPE: case BASE_TYPE_UTYPE: return GenTypeRef(type.enum_def);
return GenTypeRef(type.enum_def); default: return GenType(GenNativeType(type.base_type));
default:
return GenType(GenNativeType(type.base_type));
} }
} }
@@ -130,35 +123,29 @@ class JsonSchemaGenerator : public BaseGenerator {
code_ += "{"; code_ += "{";
code_ += " \"$schema\": \"http://json-schema.org/draft-04/schema#\","; code_ += " \"$schema\": \"http://json-schema.org/draft-04/schema#\",";
code_ += " \"definitions\": {"; code_ += " \"definitions\": {";
for (auto e = parser_.enums_.vec.cbegin(); for (auto e = parser_.enums_.vec.cbegin(); e != parser_.enums_.vec.cend();
e != parser_.enums_.vec.cend();
++e) { ++e) {
code_ += " \"" + GenFullName(*e) + "\" : {"; code_ += " \"" + GenFullName(*e) + "\" : {";
code_ += " " + GenType("string") + ","; code_ += " " + GenType("string") + ",";
std::string enumdef(" \"enum\": ["); std::string enumdef(" \"enum\": [");
for (auto enum_value = (*e)->vals.vec.begin(); for (auto enum_value = (*e)->vals.vec.begin();
enum_value != (*e)->vals.vec.end(); enum_value != (*e)->vals.vec.end(); ++enum_value) {
++enum_value) {
enumdef.append("\"" + (*enum_value)->name + "\""); enumdef.append("\"" + (*enum_value)->name + "\"");
if (*enum_value != (*e)->vals.vec.back()) { if (*enum_value != (*e)->vals.vec.back()) { enumdef.append(", "); }
enumdef.append(", ");
}
} }
enumdef.append("]"); enumdef.append("]");
code_ += enumdef; code_ += enumdef;
code_ += " },"; // close type code_ += " },"; // close type
} }
for (auto s = parser_.structs_.vec.cbegin(); for (auto s = parser_.structs_.vec.cbegin();
s != parser_.structs_.vec.cend(); s != parser_.structs_.vec.cend(); ++s) {
++s) {
const auto &structure = *s; const auto &structure = *s;
code_ += " \"" + GenFullName(structure) + "\" : {"; code_ += " \"" + GenFullName(structure) + "\" : {";
code_ += " " + GenType("object") + ","; code_ += " " + GenType("object") + ",";
std::string comment; std::string comment;
const auto &comment_lines = structure->doc_comment; const auto &comment_lines = structure->doc_comment;
for (auto comment_line = comment_lines.cbegin(); for (auto comment_line = comment_lines.cbegin();
comment_line != comment_lines.cend(); comment_line != comment_lines.cend(); ++comment_line) {
++comment_line) {
comment.append(*comment_line); comment.append(*comment_line);
} }
if (comment.size() > 0) { if (comment.size() > 0) {
@@ -169,10 +156,9 @@ class JsonSchemaGenerator : public BaseGenerator {
const auto &properties = structure->fields.vec; const auto &properties = structure->fields.vec;
for (auto prop = properties.cbegin(); prop != properties.cend(); ++prop) { for (auto prop = properties.cbegin(); prop != properties.cend(); ++prop) {
const auto &property = *prop; const auto &property = *prop;
std::string typeLine(" \"" + property->name + "\" : { " + GenType(property->value.type) + " }"); std::string typeLine(" \"" + property->name + "\" : { " +
if (property != properties.back()) { GenType(property->value.type) + " }");
typeLine.append(","); if (property != properties.back()) { typeLine.append(","); }
}
code_ += typeLine; code_ += typeLine;
} }
code_ += " },"; // close properties code_ += " },"; // close properties
@@ -184,8 +170,7 @@ class JsonSchemaGenerator : public BaseGenerator {
if (requiredProperties.size() > 0) { if (requiredProperties.size() > 0) {
std::string required_string(" \"required\" : ["); std::string required_string(" \"required\" : [");
for (auto req_prop = requiredProperties.cbegin(); for (auto req_prop = requiredProperties.cbegin();
req_prop != requiredProperties.cend(); req_prop != requiredProperties.cend(); ++req_prop) {
++req_prop) {
required_string.append("\"" + (*req_prop)->name + "\""); required_string.append("\"" + (*req_prop)->name + "\"");
if (*req_prop != requiredProperties.back()) { if (*req_prop != requiredProperties.back()) {
required_string.append(", "); required_string.append(", ");
@@ -196,9 +181,7 @@ class JsonSchemaGenerator : public BaseGenerator {
} }
code_ += " \"additionalProperties\" : false"; code_ += " \"additionalProperties\" : false";
std::string closeType(" }"); std::string closeType(" }");
if (*s != parser_.structs_.vec.back()) { if (*s != parser_.structs_.vec.back()) { closeType.append(","); }
closeType.append(",");
}
code_ += closeType; // close type code_ += closeType; // close type
} }
code_ += " },"; // close definitions code_ += " },"; // close definitions

View File

@@ -18,10 +18,10 @@
#include <string> #include <string>
#include "flatbuffers/code_generators.h"
#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 "flatbuffers/code_generators.h"
namespace flatbuffers { namespace flatbuffers {
namespace php { namespace php {
@@ -40,8 +40,8 @@ namespace php {
private: private:
bool generateEnums() { bool generateEnums() {
for (auto it = parser_.enums_.vec.begin(); for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
it != parser_.enums_.vec.end(); ++it) { ++it) {
auto &enum_def = **it; auto &enum_def = **it;
std::string enumcode; std::string enumcode;
GenEnum(enum_def, &enumcode); GenEnum(enum_def, &enumcode);
@@ -62,8 +62,8 @@ namespace php {
} }
// Begin by declaring namespace and imports. // Begin by declaring namespace and imports.
void BeginFile(const std::string name_space_name, void BeginFile(const std::string name_space_name, const bool needs_imports,
const bool needs_imports, std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += "<?php\n"; code += "<?php\n";
code = code + "// " + FlatBuffersGeneratedWarning() + "\n\n"; code = code + "// " + FlatBuffersGeneratedWarning() + "\n\n";
@@ -87,12 +87,12 @@ namespace php {
if (!classcode.length()) return true; if (!classcode.length()) return true;
std::string code = ""; std::string code = "";
BeginFile(FullNamespace("\\", *def.defined_namespace), BeginFile(FullNamespace("\\", *def.defined_namespace), needs_imports,
needs_imports, &code); &code);
code += classcode; code += classcode;
std::string filename = NamespaceDir(*def.defined_namespace) + std::string filename =
def.name + ".php"; NamespaceDir(*def.defined_namespace) + def.name + ".php";
return SaveFile(filename.c_str(), code, false); return SaveFile(filename.c_str(), code, false);
} }
@@ -173,8 +173,7 @@ namespace php {
} }
// Get the length of a vector. // Get the length of a vector.
static void GetVectorLen(const FieldDef &field, static void GetVectorLen(const FieldDef &field, std::string *code_ptr) {
std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += Indent + "/**\n"; code += Indent + "/**\n";
@@ -191,8 +190,7 @@ namespace php {
} }
// Get a [ubyte] vector as a byte array. // Get a [ubyte] vector as a byte array.
static void GetUByte(const FieldDef &field, static void GetUByte(const FieldDef &field, std::string *code_ptr) {
std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += Indent + "/**\n"; code += Indent + "/**\n";
@@ -242,10 +240,9 @@ namespace php {
code += MakeCamel(field.name); code += MakeCamel(field.name);
code += "()\n"; code += "()\n";
code += Indent + "{\n"; code += Indent + "{\n";
code += Indent + Indent + code += Indent + Indent + "$o = $this->__offset(" +
"$o = $this->__offset(" + NumToString(field.value.offset) + ");\n" + Indent + Indent +
NumToString(field.value.offset) + "return $o != 0 ? ";
");\n" + Indent + Indent + "return $o != 0 ? ";
code += "$this->bb->get"; code += "$this->bb->get";
code += MakeCamel(GenTypeGet(field.value.type)) + "($o + $this->bb_pos)"; code += MakeCamel(GenTypeGet(field.value.type)) + "($o + $this->bb_pos)";
code += " : " + GenDefaultValue(field.value) + ";\n"; code += " : " + GenDefaultValue(field.value) + ";\n";
@@ -282,14 +279,11 @@ namespace php {
code += Indent + "{\n"; code += Indent + "{\n";
code += Indent + Indent + "$obj = new "; code += Indent + Indent + "$obj = new ";
code += MakeCamel(GenTypeGet(field.value.type)) + "();\n"; code += MakeCamel(GenTypeGet(field.value.type)) + "();\n";
code += Indent + Indent + code += Indent + Indent + "$o = $this->__offset(" +
"$o = $this->__offset(" + NumToString(field.value.offset) + ");\n";
NumToString(field.value.offset) +
");\n";
code += Indent + Indent; code += Indent + Indent;
code += "return $o != 0 ? $obj->init("; code += "return $o != 0 ? $obj->init(";
if (field.value.type.struct_def->fixed) if (field.value.type.struct_def->fixed) {
{
code += "$o + $this->bb_pos, $this->bb) : "; code += "$o + $this->bb_pos, $this->bb) : ";
} else { } else {
code += "$this->__indirect($o + $this->bb_pos), $this->bb) : "; code += "$this->__indirect($o + $this->bb_pos), $this->bb) : ";
@@ -305,10 +299,8 @@ namespace php {
code += MakeCamel(field.name); code += MakeCamel(field.name);
code += "()\n"; code += "()\n";
code += Indent + "{\n"; code += Indent + "{\n";
code += Indent + Indent + code += Indent + Indent + "$o = $this->__offset(" +
"$o = $this->__offset(" + NumToString(field.value.offset) + ");\n";
NumToString(field.value.offset) +
");\n";
code += Indent + Indent; code += Indent + Indent;
code += "return $o != 0 ? $this->__string($o + $this->bb_pos) : "; code += "return $o != 0 ? $this->__string($o + $this->bb_pos) : ";
code += GenDefaultValue(field.value) + ";\n"; code += GenDefaultValue(field.value) + ";\n";
@@ -325,10 +317,8 @@ namespace php {
code += Indent + "public function get"; code += Indent + "public function get";
code += MakeCamel(field.name) + "($obj)\n"; code += MakeCamel(field.name) + "($obj)\n";
code += Indent + "{\n"; code += Indent + "{\n";
code += Indent + Indent + code += Indent + Indent + "$o = $this->__offset(" +
"$o = $this->__offset(" + NumToString(field.value.offset) + ");\n";
NumToString(field.value.offset) +
");\n";
code += Indent + Indent; code += Indent + Indent;
code += "return $o != 0 ? $this->__union($obj, $o) : null;\n"; code += "return $o != 0 ? $this->__union($obj, $o) : null;\n";
code += Indent + "}\n\n"; code += Indent + "}\n\n";
@@ -347,10 +337,8 @@ namespace php {
code += MakeCamel(field.name); code += MakeCamel(field.name);
code += "($j)\n"; code += "($j)\n";
code += Indent + "{\n"; code += Indent + "{\n";
code += Indent + Indent + code += Indent + Indent + "$o = $this->__offset(" +
"$o = $this->__offset(" + NumToString(field.value.offset) + ");\n";
NumToString(field.value.offset) +
");\n";
code += Indent + Indent + "$obj = new "; code += Indent + Indent + "$obj = new ";
code += MakeCamel(GenTypeGet(field.value.type)) + "();\n"; code += MakeCamel(GenTypeGet(field.value.type)) + "();\n";
@@ -358,8 +346,8 @@ namespace php {
case BASE_TYPE_STRUCT: case BASE_TYPE_STRUCT:
if (struct_def.fixed) { if (struct_def.fixed) {
code += Indent + Indent; code += Indent + Indent;
code += "return $o != 0 ? $obj->init($this->bb_pos +" code += "return $o != 0 ? $obj->init($this->bb_pos +" +
+ NumToString(field.value.offset) + ", $this->bb) : null;\n"; NumToString(field.value.offset) + ", $this->bb) : null;\n";
} else { } else {
code += Indent + Indent + "return $o != 0 ? $obj->init("; code += Indent + Indent + "return $o != 0 ? $obj->init(";
code += field.value.type.struct_def->fixed code += field.value.type.struct_def->fixed
@@ -389,8 +377,7 @@ namespace php {
code += Indent + Indent + "return $o != 0 ? $this->"; code += Indent + Indent + "return $o != 0 ? $this->";
code += GenGetter(field.value.type) + "($obj, $o); null;\n"; code += GenGetter(field.value.type) + "($obj, $o); null;\n";
break; break;
default: default: break;
break;
} }
code += Indent + "}\n\n"; code += Indent + "}\n\n";
@@ -411,10 +398,8 @@ namespace php {
code += MakeCamel(field.name); code += MakeCamel(field.name);
code += "($j)\n"; code += "($j)\n";
code += Indent + "{\n"; code += Indent + "{\n";
code += Indent + Indent + code += Indent + Indent + "$o = $this->__offset(" +
"$o = $this->__offset(" + NumToString(field.value.offset) + ");\n";
NumToString(field.value.offset) +
");\n";
if (field.value.type.VectorType().base_type == BASE_TYPE_STRING) { if (field.value.type.VectorType().base_type == BASE_TYPE_STRING) {
code += Indent + Indent; code += Indent + Indent;
@@ -433,8 +418,7 @@ namespace php {
// Get the value of a vector's union member. Uses a named return // Get the value of a vector's union member. Uses a named return
// argument to conveniently set the zero value for the result. // argument to conveniently set the zero value for the result.
void GetMemberOfVectorOfUnion(const FieldDef &field, void GetMemberOfVectorOfUnion(const FieldDef &field, std::string *code_ptr) {
std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
auto vectortype = field.value.type.VectorType(); auto vectortype = field.value.type.VectorType();
@@ -446,10 +430,8 @@ namespace php {
code += MakeCamel(field.name); code += MakeCamel(field.name);
code += "($j, $obj)\n"; code += "($j, $obj)\n";
code += Indent + "{\n"; code += Indent + "{\n";
code += Indent + Indent + code += Indent + Indent + "$o = $this->__offset(" +
"$o = $this->__offset(" + NumToString(field.value.offset) + ");\n";
NumToString(field.value.offset) +
");\n";
code += Indent + Indent + "return $o != 0 ? "; code += Indent + Indent + "return $o != 0 ? ";
code += "$this->__union($obj, $this->__vector($o) + $j * "; code += "$this->__union($obj, $this->__vector($o) + $j * ";
code += NumToString(InlineSize(vectortype)) + " - $this->bb_pos) : null;\n"; code += NumToString(InlineSize(vectortype)) + " - $this->bb_pos) : null;\n";
@@ -459,11 +441,9 @@ namespace php {
// Recursively generate arguments for a constructor, to deal with nested // Recursively generate arguments for a constructor, to deal with nested
// structs. // structs.
static void StructBuilderArgs(const StructDef &struct_def, static void StructBuilderArgs(const StructDef &struct_def,
const char *nameprefix, const char *nameprefix, std::string *code_ptr) {
std::string *code_ptr) {
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 (IsStruct(field.value.type)) { if (IsStruct(field.value.type)) {
// Generate arguments for a struct inside a struct. To ensure names // Generate arguments for a struct inside a struct. To ensure names
@@ -471,8 +451,7 @@ namespace php {
// these arguments are constructing // these arguments are constructing
// a nested struct, prefix the name with the field name. // a nested struct, prefix the name with the field name.
StructBuilderArgs(*field.value.type.struct_def, StructBuilderArgs(*field.value.type.struct_def,
(nameprefix + (field.name + "_")).c_str(), (nameprefix + (field.name + "_")).c_str(), code_ptr);
code_ptr);
} else { } else {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += (std::string) ", $" + nameprefix; code += (std::string) ", $" + nameprefix;
@@ -484,15 +463,13 @@ namespace php {
// Recursively generate struct construction statements and instert manual // Recursively generate struct construction statements and instert manual
// padding. // padding.
static void StructBuilderBody(const StructDef &struct_def, static void StructBuilderBody(const StructDef &struct_def,
const char *nameprefix, const char *nameprefix, std::string *code_ptr) {
std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += Indent + Indent + "$builder->prep("; code += Indent + Indent + "$builder->prep(";
code += NumToString(struct_def.minalign) + ", "; code += NumToString(struct_def.minalign) + ", ";
code += NumToString(struct_def.bytesize) + ");\n"; code += NumToString(struct_def.bytesize) + ");\n";
for (auto it = struct_def.fields.vec.rbegin(); for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); it != struct_def.fields.vec.rend(); ++it) {
++it) {
auto &field = **it; auto &field = **it;
if (field.padding) { if (field.padding) {
code += Indent + Indent + "$builder->pad("; code += Indent + Indent + "$builder->pad(";
@@ -500,8 +477,7 @@ namespace php {
} }
if (IsStruct(field.value.type)) { if (IsStruct(field.value.type)) {
StructBuilderBody(*field.value.type.struct_def, StructBuilderBody(*field.value.type.struct_def,
(nameprefix + (field.name + "_")).c_str(), (nameprefix + (field.name + "_")).c_str(), code_ptr);
code_ptr);
} else { } else {
code += Indent + Indent + "$builder->put" + GenMethod(field) + "($"; code += Indent + Indent + "$builder->put" + GenMethod(field) + "($";
code += nameprefix + MakeCamel(field.name, false) + ");\n"; code += nameprefix + MakeCamel(field.name, false) + ");\n";
@@ -534,15 +510,12 @@ namespace php {
code += "(FlatBufferBuilder $builder, "; code += "(FlatBufferBuilder $builder, ";
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) continue; if (field.deprecated) continue;
code += "$" + field.name; code += "$" + field.name;
if (!(it == (--struct_def.fields.vec.end()))) { if (!(it == (--struct_def.fields.vec.end()))) { code += ", "; }
code += ", ";
}
} }
code += ")\n"; code += ")\n";
code += Indent + "{\n"; code += Indent + "{\n";
@@ -550,8 +523,7 @@ namespace php {
code += NumToString(struct_def.fields.vec.size()); code += NumToString(struct_def.fields.vec.size());
code += ");\n"; code += ");\n";
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) continue; if (field.deprecated) continue;
@@ -562,8 +534,7 @@ namespace php {
code += Indent + Indent + "$o = $builder->endObject();\n"; code += Indent + Indent + "$o = $builder->endObject();\n";
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 && field.required) { if (!field.deprecated && field.required) {
code += Indent + Indent + "$builder->required($o, "; code += Indent + Indent + "$builder->required($o, ";
@@ -576,12 +547,10 @@ namespace php {
} }
// Set the value of a table's field. // Set the value of a table's field.
static void BuildFieldOfTable(const FieldDef &field, static void BuildFieldOfTable(const FieldDef &field, const size_t offset,
const size_t offset,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += Indent + "/**\n"; code += Indent + "/**\n";
code += Indent + " * @param FlatBufferBuilder $builder\n"; code += Indent + " * @param FlatBufferBuilder $builder\n";
code += Indent + " * @param " + GenTypeBasic(field.value.type) + "\n"; code += Indent + " * @param " + GenTypeBasic(field.value.type) + "\n";
@@ -597,7 +566,6 @@ namespace php {
code += GenMethod(field) + "X("; code += GenMethod(field) + "X(";
code += NumToString(offset) + ", "; code += NumToString(offset) + ", ";
code += "$" + MakeCamel(field.name, false); code += "$" + MakeCamel(field.name, false);
code += ", "; code += ", ";
@@ -611,8 +579,7 @@ namespace php {
} }
// Set the value of one of the members of a table's vector. // Set the value of one of the members of a table's vector.
static void BuildVectorOfTable(const FieldDef &field, static void BuildVectorOfTable(const FieldDef &field, std::string *code_ptr) {
std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
auto vector_type = field.value.type.VectorType(); auto vector_type = field.value.type.VectorType();
@@ -646,7 +613,6 @@ namespace php {
code += Indent + Indent + "return $builder->endVector();\n"; code += Indent + Indent + "return $builder->endVector();\n";
code += Indent + "}\n\n"; code += Indent + "}\n\n";
code += Indent + "/**\n"; code += Indent + "/**\n";
code += Indent + " * @param FlatBufferBuilder $builder\n"; code += Indent + " * @param FlatBufferBuilder $builder\n";
code += Indent + " * @param int $numElems\n"; code += Indent + " * @param int $numElems\n";
@@ -667,7 +633,6 @@ namespace php {
void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) { void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += Indent + "/**\n"; code += Indent + "/**\n";
code += Indent + " * @param FlatBufferBuilder $builder\n"; code += Indent + " * @param FlatBufferBuilder $builder\n";
code += Indent + " * @return int table offset\n"; code += Indent + " * @return int table offset\n";
@@ -677,10 +642,8 @@ namespace php {
code += Indent + "{\n"; code += Indent + "{\n";
code += Indent + Indent + "$o = $builder->endObject();\n"; code += Indent + Indent + "$o = $builder->endObject();\n";
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 && field.required) { if (!field.deprecated && field.required) {
code += Indent + Indent + "$builder->required($o, "; code += Indent + Indent + "$builder->required($o, ";
@@ -726,9 +689,7 @@ namespace php {
GetStructFieldOfTable(field, code_ptr); GetStructFieldOfTable(field, code_ptr);
} }
break; break;
case BASE_TYPE_STRING: case BASE_TYPE_STRING: GetStringField(field, code_ptr); break;
GetStringField(field, code_ptr);
break;
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType(); auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_UNION) { if (vectortype.base_type == BASE_TYPE_UNION) {
@@ -740,11 +701,8 @@ namespace php {
} }
break; break;
} }
case BASE_TYPE_UNION: case BASE_TYPE_UNION: GetUnionField(field, code_ptr); break;
GetUnionField(field, code_ptr); default: assert(0);
break;
default:
assert(0);
} }
} }
if (field.value.type.base_type == BASE_TYPE_VECTOR) { if (field.value.type.base_type == BASE_TYPE_VECTOR) {
@@ -760,8 +718,7 @@ namespace php {
GetStartOfTable(struct_def, code_ptr); GetStartOfTable(struct_def, code_ptr);
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) continue; if (field.deprecated) continue;
@@ -787,8 +744,7 @@ namespace php {
} }
// Generate struct or table methods. // Generate struct or table methods.
void GenStruct(const StructDef &struct_def, void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
std::string *code_ptr) {
if (struct_def.generated) return; if (struct_def.generated) return;
GenComment(struct_def.doc_comment, code_ptr, nullptr); GenComment(struct_def.doc_comment, code_ptr, nullptr);
@@ -836,8 +792,7 @@ namespace php {
// accessor object. This is to allow object reuse. // accessor object. This is to allow object reuse.
InitializeExisting(struct_def, code_ptr); InitializeExisting(struct_def, code_ptr);
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) continue; if (field.deprecated) continue;
@@ -860,8 +815,7 @@ namespace php {
GenComment(enum_def.doc_comment, code_ptr, nullptr); GenComment(enum_def.doc_comment, code_ptr, nullptr);
BeginEnum(enum_def.name, code_ptr); BeginEnum(enum_def.name, code_ptr);
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
it != enum_def.vals.vec.end();
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
GenComment(ev.doc_comment, code_ptr, nullptr); GenComment(ev.doc_comment, code_ptr, nullptr);
@@ -871,8 +825,8 @@ namespace php {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += "\n"; code += "\n";
code += Indent + "private static $names = array(\n"; code += Indent + "private static $names = array(\n";
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
it != enum_def.vals.vec.end(); ++it) { ++it) {
auto &ev = **it; auto &ev = **it;
code += Indent + Indent + "\"" + ev.name + "\",\n"; code += Indent + Indent + "\"" + ev.name + "\",\n";
} }
@@ -895,8 +849,7 @@ namespace php {
case BASE_TYPE_STRUCT: return "__struct"; case BASE_TYPE_STRUCT: return "__struct";
case BASE_TYPE_UNION: return "__union"; case BASE_TYPE_UNION: return "__union";
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
default: default: return "Get";
return "Get";
} }
} }
@@ -909,11 +862,13 @@ namespace php {
static std::string GenTypeBasic(const Type &type) { static std::string GenTypeBasic(const Type &type) {
static const char *ctypename[] = { static const char *ctypename[] = {
// clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#NTYPE, #NTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD #undef FLATBUFFERS_TD
// clang-format on
}; };
return ctypename[type.base_type]; return ctypename[type.base_type];
} }
@@ -927,11 +882,9 @@ namespace php {
} }
switch (value.type.base_type) { switch (value.type.base_type) {
case BASE_TYPE_BOOL: case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true";
return value.constant == "0" ? "false" : "true";
case BASE_TYPE_STRING: case BASE_TYPE_STRING: return "null";
return "null";
case BASE_TYPE_LONG: case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: case BASE_TYPE_ULONG:
@@ -941,30 +894,23 @@ namespace php {
} }
return "0"; return "0";
default: default: return value.constant;
return value.constant;
} }
} }
static std::string GenTypePointer(const Type &type) { static std::string GenTypePointer(const Type &type) {
switch (type.base_type) { switch (type.base_type) {
case BASE_TYPE_STRING: case BASE_TYPE_STRING: return "string";
return "string"; case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
case BASE_TYPE_VECTOR: case BASE_TYPE_STRUCT: return type.struct_def->name;
return GenTypeGet(type.VectorType());
case BASE_TYPE_STRUCT:
return type.struct_def->name;
case BASE_TYPE_UNION: case BASE_TYPE_UNION:
// fall through // fall through
default: default: return "Table";
return "Table";
} }
} }
static std::string GenTypeGet(const Type &type) { static std::string GenTypeGet(const Type &type) {
return IsScalar(type.base_type) return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
? GenTypeBasic(type)
: GenTypePointer(type);
} }
// Create a struct with a builder and the struct's arguments. // Create a struct with a builder and the struct's arguments.
@@ -986,7 +932,6 @@ namespace php {
code += Indent + Indent + "return $builder->offset();\n"; code += Indent + Indent + "return $builder->offset();\n";
code += Indent + "}\n"; code += Indent + "}\n";
} }
}; };
} // namespace php } // namespace php

View File

@@ -18,10 +18,10 @@
#include <string> #include <string>
#include "flatbuffers/code_generators.h"
#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 "flatbuffers/code_generators.h"
namespace flatbuffers { namespace flatbuffers {
namespace python { namespace python {
@@ -35,7 +35,6 @@ static std::string GenTypeBasic(const Type &type);
static std::string GenTypeGet(const Type &type); static std::string GenTypeGet(const Type &type);
static std::string TypeName(const FieldDef &field); static std::string TypeName(const FieldDef &field);
// Hardcode spaces per indentation. // Hardcode spaces per indentation.
const std::string Indent = " "; const std::string Indent = " ";
@@ -44,9 +43,8 @@ const std::string Indent = " ";
std::string OffsetPrefix(const FieldDef &field) { std::string OffsetPrefix(const FieldDef &field) {
return "\n" + Indent + Indent + return "\n" + Indent + Indent +
"o = flatbuffers.number_types.UOffsetTFlags.py_type" + "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
"(self._tab.Offset(" + "(self._tab.Offset(" + NumToString(field.value.offset) + "))\n" +
NumToString(field.value.offset) + Indent + Indent + "if o != 0:\n";
"))\n" + Indent + Indent + "if o != 0:\n";
} }
// Begin a class declaration. // Begin a class declaration.
@@ -109,8 +107,7 @@ static void InitializeExisting(const StructDef &struct_def,
} }
// Get the length of a vector. // Get the length of a vector.
static void GetVectorLen(const StructDef &struct_def, static void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
const FieldDef &field,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
@@ -188,8 +185,7 @@ static void GetStructFieldOfTable(const StructDef &struct_def,
} }
// Get the value of a string. // Get the value of a string.
static void GetStringField(const StructDef &struct_def, static void GetStringField(const StructDef &struct_def, const FieldDef &field,
const FieldDef &field,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr); GenReceiver(struct_def, code_ptr);
@@ -202,8 +198,7 @@ static void GetStringField(const StructDef &struct_def,
} }
// Get the value of a union from an object. // Get the value of a union from an object.
static void GetUnionField(const StructDef &struct_def, static void GetUnionField(const StructDef &struct_def, const FieldDef &field,
const FieldDef &field,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr); GenReceiver(struct_def, code_ptr);
@@ -284,9 +279,7 @@ static void GetVectorOfNonStructAsNumpy(const StructDef &struct_def,
// Currently, we only support accessing as numpy array if // Currently, we only support accessing as numpy array if
// the vector type is a scalar. // the vector type is a scalar.
if (!(IsScalar(vectortype.base_type))) { if (!(IsScalar(vectortype.base_type))) { return; }
return;
}
GenReceiver(struct_def, code_ptr); GenReceiver(struct_def, code_ptr);
code += MakeCamel(field.name) + "AsNumpy(self):"; code += MakeCamel(field.name) + "AsNumpy(self):";
@@ -319,19 +312,16 @@ static void BeginBuilderArgs(const StructDef &struct_def,
// Recursively generate arguments for a constructor, to deal with nested // Recursively generate arguments for a constructor, to deal with nested
// structs. // structs.
static void StructBuilderArgs(const StructDef &struct_def, static void StructBuilderArgs(const StructDef &struct_def,
const char *nameprefix, const char *nameprefix, std::string *code_ptr) {
std::string *code_ptr) {
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 (IsStruct(field.value.type)) { if (IsStruct(field.value.type)) {
// Generate arguments for a struct inside a struct. To ensure names // Generate arguments for a struct inside a struct. To ensure names
// don't clash, and to make it obvious these arguments are constructing // don't clash, and to make it obvious these arguments are constructing
// a nested struct, prefix the name with the field name. // a nested struct, prefix the name with the field name.
StructBuilderArgs(*field.value.type.struct_def, StructBuilderArgs(*field.value.type.struct_def,
(nameprefix + (field.name + "_")).c_str(), (nameprefix + (field.name + "_")).c_str(), code_ptr);
code_ptr);
} else { } else {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += (std::string) ", " + nameprefix; code += (std::string) ", " + nameprefix;
@@ -349,21 +339,18 @@ static void EndBuilderArgs(std::string *code_ptr) {
// Recursively generate struct construction statements and instert manual // Recursively generate struct construction statements and instert manual
// padding. // padding.
static void StructBuilderBody(const StructDef &struct_def, static void StructBuilderBody(const StructDef &struct_def,
const char *nameprefix, const char *nameprefix, std::string *code_ptr) {
std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += " builder.Prep(" + NumToString(struct_def.minalign) + ", "; code += " builder.Prep(" + NumToString(struct_def.minalign) + ", ";
code += NumToString(struct_def.bytesize) + ")\n"; code += NumToString(struct_def.bytesize) + ")\n";
for (auto it = struct_def.fields.vec.rbegin(); for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); it != struct_def.fields.vec.rend(); ++it) {
++it) {
auto &field = **it; auto &field = **it;
if (field.padding) if (field.padding)
code += " builder.Pad(" + NumToString(field.padding) + ")\n"; code += " builder.Pad(" + NumToString(field.padding) + ")\n";
if (IsStruct(field.value.type)) { if (IsStruct(field.value.type)) {
StructBuilderBody(*field.value.type.struct_def, StructBuilderBody(*field.value.type.struct_def,
(nameprefix + (field.name + "_")).c_str(), (nameprefix + (field.name + "_")).c_str(), code_ptr);
code_ptr);
} else { } else {
code += " builder.Prepend" + GenMethod(field) + "("; code += " builder.Prepend" + GenMethod(field) + "(";
code += nameprefix + MakeCamel(field.name, false) + ")\n"; code += nameprefix + MakeCamel(field.name, false) + ")\n";
@@ -389,8 +376,7 @@ static void GetStartOfTable(const StructDef &struct_def,
// Set the value of a table's field. // Set the value of a table's field.
static void BuildFieldOfTable(const StructDef &struct_def, static void BuildFieldOfTable(const StructDef &struct_def,
const FieldDef &field, const FieldDef &field, const size_t offset,
const size_t offset,
std::string *code_ptr) { std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += "def " + struct_def.name + "Add" + MakeCamel(field.name); code += "def " + struct_def.name + "Add" + MakeCamel(field.name);
@@ -413,8 +399,7 @@ static void BuildFieldOfTable(const StructDef &struct_def,
// Set the value of one of the members of a table's vector. // Set the value of one of the members of a table's vector.
static void BuildVectorOfTable(const StructDef &struct_def, static void BuildVectorOfTable(const StructDef &struct_def,
const FieldDef &field, const FieldDef &field, std::string *code_ptr) {
std::string *code_ptr) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code += "def " + struct_def.name + "Start"; code += "def " + struct_def.name + "Start";
code += MakeCamel(field.name); code += MakeCamel(field.name);
@@ -445,8 +430,7 @@ static void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
// Generate a struct field, conditioned on its child type(s). // Generate a struct field, conditioned on its child type(s).
static void GenStructAccessor(const StructDef &struct_def, static void GenStructAccessor(const StructDef &struct_def,
const FieldDef &field, const FieldDef &field, std::string *code_ptr) {
std::string *code_ptr) {
GenComment(field.doc_comment, code_ptr, nullptr, "# "); GenComment(field.doc_comment, code_ptr, nullptr, "# ");
if (IsScalar(field.value.type.base_type)) { if (IsScalar(field.value.type.base_type)) {
if (struct_def.fixed) { if (struct_def.fixed) {
@@ -463,9 +447,7 @@ static void GenStructAccessor(const StructDef &struct_def,
GetStructFieldOfTable(struct_def, field, code_ptr); GetStructFieldOfTable(struct_def, field, code_ptr);
} }
break; break;
case BASE_TYPE_STRING: case BASE_TYPE_STRING: GetStringField(struct_def, field, code_ptr); break;
GetStringField(struct_def, field, code_ptr);
break;
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType(); auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_STRUCT) { if (vectortype.base_type == BASE_TYPE_STRUCT) {
@@ -476,11 +458,8 @@ static void GenStructAccessor(const StructDef &struct_def,
} }
break; break;
} }
case BASE_TYPE_UNION: case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
GetUnionField(struct_def, field, code_ptr); default: assert(0);
break;
default:
assert(0);
} }
} }
if (field.value.type.base_type == BASE_TYPE_VECTOR) { if (field.value.type.base_type == BASE_TYPE_VECTOR) {
@@ -494,8 +473,7 @@ static void GenTableBuilders(const StructDef &struct_def,
GetStartOfTable(struct_def, code_ptr); GetStartOfTable(struct_def, code_ptr);
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) continue; if (field.deprecated) continue;
@@ -510,8 +488,7 @@ static void GenTableBuilders(const StructDef &struct_def,
} }
// Generate struct or table methods. // Generate struct or table methods.
static void GenStruct(const StructDef &struct_def, static void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
std::string *code_ptr) {
if (struct_def.generated) return; if (struct_def.generated) return;
GenComment(struct_def.doc_comment, code_ptr, nullptr, "# "); GenComment(struct_def.doc_comment, code_ptr, nullptr, "# ");
@@ -525,8 +502,7 @@ static void GenStruct(const StructDef &struct_def,
// accessor object. This is to allow object reuse. // accessor object. This is to allow object reuse.
InitializeExisting(struct_def, code_ptr); InitializeExisting(struct_def, code_ptr);
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) continue; if (field.deprecated) continue;
@@ -548,8 +524,7 @@ static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
GenComment(enum_def.doc_comment, code_ptr, nullptr, "# "); GenComment(enum_def.doc_comment, code_ptr, nullptr, "# ");
BeginEnum(enum_def.name, code_ptr); BeginEnum(enum_def.name, code_ptr);
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
it != enum_def.vals.vec.end();
++it) { ++it) {
auto &ev = **it; auto &ev = **it;
GenComment(ev.doc_comment, code_ptr, nullptr, "# "); GenComment(ev.doc_comment, code_ptr, nullptr, "# ");
@@ -565,9 +540,8 @@ static std::string GenGetter(const Type &type) {
case BASE_TYPE_UNION: return "self._tab.Union("; case BASE_TYPE_UNION: return "self._tab.Union(";
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
default: default:
return "self._tab.Get(flatbuffers.number_types." + \ return "self._tab.Get(flatbuffers.number_types." +
MakeCamel(GenTypeGet(type)) + \ MakeCamel(GenTypeGet(type)) + "Flags, ";
"Flags, ";
} }
} }
@@ -580,34 +554,30 @@ static std::string GenMethod(const FieldDef &field) {
static std::string GenTypeBasic(const Type &type) { static std::string GenTypeBasic(const Type &type) {
static const char *ctypename[] = { static const char *ctypename[] = {
// clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#PTYPE, #PTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD #undef FLATBUFFERS_TD
// clang-format on
}; };
return ctypename[type.base_type]; return ctypename[type.base_type];
} }
static std::string GenTypePointer(const Type &type) { static std::string GenTypePointer(const Type &type) {
switch (type.base_type) { switch (type.base_type) {
case BASE_TYPE_STRING: case BASE_TYPE_STRING: return "string";
return "string"; case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
case BASE_TYPE_VECTOR: case BASE_TYPE_STRUCT: return type.struct_def->name;
return GenTypeGet(type.VectorType());
case BASE_TYPE_STRUCT:
return type.struct_def->name;
case BASE_TYPE_UNION: case BASE_TYPE_UNION:
// fall through // fall through
default: default: return "*flatbuffers.Table";
return "*flatbuffers.Table";
} }
} }
static std::string GenTypeGet(const Type &type) { static std::string GenTypeGet(const Type &type) {
return IsScalar(type.base_type) return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
? GenTypeBasic(type)
: GenTypePointer(type);
} }
static std::string TypeName(const FieldDef &field) { static std::string TypeName(const FieldDef &field) {
@@ -666,9 +636,7 @@ class PythonGenerator : public BaseGenerator {
std::string &code = *code_ptr; std::string &code = *code_ptr;
code = code + "# " + FlatBuffersGeneratedWarning() + "\n\n"; code = code + "# " + FlatBuffersGeneratedWarning() + "\n\n";
code += "# namespace: " + name_space_name + "\n\n"; code += "# namespace: " + name_space_name + "\n\n";
if (needs_imports) { if (needs_imports) { code += "import flatbuffers\n\n"; }
code += "import flatbuffers\n\n";
}
} }
// Save out the generated code for a Python Table type. // Save out the generated code for a Python Table type.
@@ -688,8 +656,8 @@ class PythonGenerator : public BaseGenerator {
std::string code = ""; std::string code = "";
BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code); BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
code += classcode; code += classcode;
std::string filename = NamespaceDir(*def.defined_namespace) + std::string filename =
def.name + ".py"; NamespaceDir(*def.defined_namespace) + def.name + ".py";
return SaveFile(filename.c_str(), code, false); return SaveFile(filename.c_str(), code, false);
} }
}; };

View File

@@ -17,15 +17,14 @@
// independent from idl_parser, since this code is not needed for most clients // independent from idl_parser, since this code is not needed for most clients
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
#include "flatbuffers/flexbuffers.h"
#include "flatbuffers/idl.h" #include "flatbuffers/idl.h"
#include "flatbuffers/util.h" #include "flatbuffers/util.h"
#include "flatbuffers/flexbuffers.h"
namespace flatbuffers { namespace flatbuffers {
static bool GenStruct(const StructDef &struct_def, const Table *table, static bool GenStruct(const StructDef &struct_def, const Table *table,
int indent, const IDLOptions &opts, int indent, const IDLOptions &opts, std::string *_text);
std::string *_text);
// If indentation is less than 0, that indicates we don't want any newlines // If indentation is less than 0, that indicates we don't want any newlines
// either. // either.
@@ -33,9 +32,7 @@ const char *NewLine(const IDLOptions &opts) {
return opts.indent_step >= 0 ? "\n" : ""; return opts.indent_step >= 0 ? "\n" : "";
} }
int Indent(const IDLOptions &opts) { int Indent(const IDLOptions &opts) { return std::max(opts.indent_step, 0); }
return std::max(opts.indent_step, 0);
}
// Output an identifier with or without quotes depending on strictness. // Output an identifier with or without quotes depending on strictness.
void OutputIdentifier(const std::string &name, const IDLOptions &opts, void OutputIdentifier(const std::string &name, const IDLOptions &opts,
@@ -49,10 +46,9 @@ void OutputIdentifier(const std::string &name, const IDLOptions &opts,
// Print (and its template specialization below for pointers) generate text // Print (and its template specialization below for pointers) generate text
// for a single FlatBuffer value into JSON format. // for a single FlatBuffer value into JSON format.
// The general case for scalars: // The general case for scalars:
template<typename T> bool Print(T val, Type type, int /*indent*/, template<typename T>
Type * /*union_type*/, bool Print(T val, Type type, int /*indent*/, Type * /*union_type*/,
const IDLOptions &opts, const IDLOptions &opts, std::string *_text) {
std::string *_text) {
std::string &text = *_text; std::string &text = *_text;
if (type.enum_def && opts.output_enum_identifiers) { if (type.enum_def && opts.output_enum_identifiers) {
auto enum_val = type.enum_def->ReverseLookup(static_cast<int>(val)); auto enum_val = type.enum_def->ReverseLookup(static_cast<int>(val));
@@ -72,9 +68,9 @@ template<typename T> bool Print(T val, Type type, int /*indent*/,
} }
// Print a vector a sequence of JSON values, comma separated, wrapped in "[]". // Print a vector a sequence of JSON values, comma separated, wrapped in "[]".
template<typename T> bool PrintVector(const Vector<T> &v, Type type, template<typename T>
int indent, const IDLOptions &opts, bool PrintVector(const Vector<T> &v, Type type, int indent,
std::string *_text) { const IDLOptions &opts, std::string *_text) {
std::string &text = *_text; std::string &text = *_text;
text += "["; text += "[";
text += NewLine(opts); text += NewLine(opts);
@@ -90,8 +86,7 @@ template<typename T> bool PrintVector(const Vector<T> &v, Type type,
return false; return false;
} }
} else { } else {
if (!Print(v[i], type, indent + Indent(opts), nullptr, if (!Print(v[i], type, indent + Indent(opts), nullptr, opts, _text)) {
opts, _text)) {
return false; return false;
} }
} }
@@ -103,10 +98,9 @@ template<typename T> bool PrintVector(const Vector<T> &v, Type type,
} }
// Specialization of Print above for pointer types. // Specialization of Print above for pointer types.
template<> bool Print<const void *>(const void *val, template<>
Type type, int indent, bool Print<const void *>(const void *val, Type type, int indent,
Type *union_type, Type *union_type, const IDLOptions &opts,
const IDLOptions &opts,
std::string *_text) { std::string *_text) {
switch (type.base_type) { switch (type.base_type) {
case BASE_TYPE_UNION: case BASE_TYPE_UNION:
@@ -116,11 +110,8 @@ template<> bool Print<const void *>(const void *val,
return Print<const void *>(val, *union_type, indent, nullptr, opts, return Print<const void *>(val, *union_type, indent, nullptr, opts,
_text); _text);
case BASE_TYPE_STRUCT: case BASE_TYPE_STRUCT:
if (!GenStruct(*type.struct_def, if (!GenStruct(*type.struct_def, reinterpret_cast<const Table *>(val),
reinterpret_cast<const Table *>(val), indent, opts, _text)) {
indent,
opts,
_text)) {
return false; return false;
} }
break; break;
@@ -135,6 +126,7 @@ template<> bool Print<const void *>(const void *val,
type = type.VectorType(); type = type.VectorType();
// Call PrintVector above specifically for each element type: // Call PrintVector above specifically for each element type:
switch (type.base_type) { switch (type.base_type) {
// clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
case BASE_TYPE_ ## ENUM: \ case BASE_TYPE_ ## ENUM: \
@@ -146,6 +138,7 @@ template<> bool Print<const void *>(const void *val,
break; break;
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD #undef FLATBUFFERS_TD
// clang-format on
} }
break; break;
default: assert(0); default: assert(0);
@@ -154,31 +147,28 @@ template<> bool Print<const void *>(const void *val,
} }
// Generate text for a scalar field. // Generate text for a scalar field.
template<typename T> static bool GenField(const FieldDef &fd, template<typename T>
const Table *table, bool fixed, static bool GenField(const FieldDef &fd, const Table *table, bool fixed,
const IDLOptions &opts, const IDLOptions &opts, int indent, std::string *_text) {
int indent, return Print(fixed ? reinterpret_cast<const Struct *>(table)->GetField<T>(
std::string *_text) { fd.value.offset)
return Print(fixed ? : table->GetField<T>(fd.value.offset, 0),
reinterpret_cast<const Struct *>(table)->GetField<T>(fd.value.offset) : fd.value.type, indent, nullptr, opts, _text);
table->GetField<T>(fd.value.offset, 0), fd.value.type, indent, nullptr,
opts, _text);
} }
static bool GenStruct(const StructDef &struct_def, const Table *table, static bool GenStruct(const StructDef &struct_def, const Table *table,
int indent, const IDLOptions &opts, int indent, const IDLOptions &opts, std::string *_text);
std::string *_text);
// Generate text for non-scalar field. // Generate text for non-scalar field.
static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed, static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
int indent, Type *union_type, int indent, Type *union_type, const IDLOptions &opts,
const IDLOptions &opts, std::string *_text) { std::string *_text) {
const void *val = nullptr; const void *val = nullptr;
if (fixed) { if (fixed) {
// The only non-scalar fields in structs are structs. // The only non-scalar fields in structs are structs.
assert(IsStruct(fd.value.type)); assert(IsStruct(fd.value.type));
val = reinterpret_cast<const Struct *>(table)-> val = reinterpret_cast<const Struct *>(table)->GetStruct<const void *>(
GetStruct<const void *>(fd.value.offset); fd.value.offset);
} else if (fd.flexbuffer) { } else if (fd.flexbuffer) {
auto vec = table->GetPointer<const Vector<uint8_t> *>(fd.value.offset); auto vec = table->GetPointer<const Vector<uint8_t> *>(fd.value.offset);
auto root = flexbuffers::GetRoot(vec->data(), vec->size()); auto root = flexbuffers::GetRoot(vec->data(), vec->size());
@@ -199,20 +189,17 @@ static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
// Generate text for a struct or table, values separated by commas, indented, // Generate text for a struct or table, values separated by commas, indented,
// and bracketed by "{}" // and bracketed by "{}"
static bool GenStruct(const StructDef &struct_def, const Table *table, static bool GenStruct(const StructDef &struct_def, const Table *table,
int indent, const IDLOptions &opts, int indent, const IDLOptions &opts, std::string *_text) {
std::string *_text) {
std::string &text = *_text; std::string &text = *_text;
text += "{"; text += "{";
int fieldout = 0; int fieldout = 0;
Type *union_type = nullptr; Type *union_type = nullptr;
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) {
FieldDef &fd = **it; FieldDef &fd = **it;
auto is_present = struct_def.fixed || table->CheckField(fd.value.offset); auto is_present = struct_def.fixed || table->CheckField(fd.value.offset);
auto output_anyway = opts.output_default_scalars_in_json && auto output_anyway = opts.output_default_scalars_in_json &&
IsScalar(fd.value.type.base_type) && IsScalar(fd.value.type.base_type) && !fd.deprecated;
!fd.deprecated;
if (is_present || output_anyway) { if (is_present || output_anyway) {
if (fieldout++) { if (fieldout++) {
if (!opts.protobuf_ascii_alike) text += ","; if (!opts.protobuf_ascii_alike) text += ",";
@@ -222,10 +209,12 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
OutputIdentifier(fd.name, opts, _text); OutputIdentifier(fd.name, opts, _text);
if (!opts.protobuf_ascii_alike || if (!opts.protobuf_ascii_alike ||
(fd.value.type.base_type != BASE_TYPE_STRUCT && (fd.value.type.base_type != BASE_TYPE_STRUCT &&
fd.value.type.base_type != BASE_TYPE_VECTOR)) text += ":"; fd.value.type.base_type != BASE_TYPE_VECTOR))
text += ":";
text += " "; text += " ";
if (is_present) { if (is_present) {
switch (fd.value.type.base_type) { switch (fd.value.type.base_type) {
// clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
case BASE_TYPE_ ## ENUM: \ case BASE_TYPE_ ## ENUM: \
@@ -247,6 +236,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
return false; return false;
} }
break; break;
// clang-format on
} }
if (fd.value.type.base_type == BASE_TYPE_UTYPE) { if (fd.value.type.base_type == BASE_TYPE_UTYPE) {
auto enum_val = fd.value.type.enum_def->ReverseLookup( auto enum_val = fd.value.type.enum_def->ReverseLookup(
@@ -254,9 +244,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
assert(enum_val); assert(enum_val);
union_type = &enum_val->union_type; union_type = &enum_val->union_type;
} }
} } else {
else
{
text += fd.value.constant; text += fd.value.constant;
} }
} }
@@ -273,11 +261,8 @@ bool GenerateText(const Parser &parser, const void *flatbuffer,
std::string &text = *_text; std::string &text = *_text;
assert(parser.root_struct_def_); // call SetRootType() assert(parser.root_struct_def_); // call SetRootType()
text.reserve(1024); // Reduce amount of inevitable reallocs. text.reserve(1024); // Reduce amount of inevitable reallocs.
if (!GenStruct(*parser.root_struct_def_, if (!GenStruct(*parser.root_struct_def_, GetRoot<Table>(flatbuffer), 0,
GetRoot<Table>(flatbuffer), parser.opts, _text)) {
0,
parser.opts,
_text)) {
return false; return false;
} }
text += NewLine(parser.opts); text += NewLine(parser.opts);
@@ -289,34 +274,29 @@ std::string TextFileName(const std::string &path,
return path + file_name + ".json"; return path + file_name + ".json";
} }
bool GenerateTextFile(const Parser &parser, bool GenerateTextFile(const Parser &parser, const std::string &path,
const std::string &path,
const std::string &file_name) { const std::string &file_name) {
if (!parser.builder_.GetSize() || !parser.root_struct_def_) return true; if (!parser.builder_.GetSize() || !parser.root_struct_def_) return true;
std::string text; std::string text;
if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &text)) { if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &text)) {
return false; return false;
} }
return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(), return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(), text,
text,
false); false);
} }
std::string TextMakeRule(const Parser &parser, std::string TextMakeRule(const Parser &parser, const std::string &path,
const std::string &path,
const std::string &file_name) { const std::string &file_name) {
if (!parser.builder_.GetSize() || !parser.root_struct_def_) return ""; if (!parser.builder_.GetSize() || !parser.root_struct_def_) return "";
std::string filebase = flatbuffers::StripPath( std::string filebase =
flatbuffers::StripExtension(file_name)); flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
std::string make_rule = TextFileName(path, filebase) + ": " + file_name; std::string make_rule = TextFileName(path, filebase) + ": " + file_name;
auto included_files = parser.GetIncludedFilesRecursive( auto included_files =
parser.root_struct_def_->file); parser.GetIncludedFilesRecursive(parser.root_struct_def_->file);
for (auto it = included_files.begin(); for (auto it = included_files.begin(); it != included_files.end(); ++it) {
it != included_files.end(); ++it) {
make_rule += " " + *it; make_rule += " " + *it;
} }
return make_rule; return make_rule;
} }
} // namespace flatbuffers } // namespace flatbuffers

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,7 @@
namespace flatbuffers { namespace flatbuffers {
int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data) { int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data) {
// clang-format off
#define FLATBUFFERS_GET(T) static_cast<int64_t>(ReadScalar<T>(data)) #define FLATBUFFERS_GET(T) static_cast<int64_t>(ReadScalar<T>(data))
switch (type) { switch (type) {
case reflection::UType: case reflection::UType:
@@ -44,6 +45,7 @@ int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data) {
default: return 0; // Tables & vectors do not make sense. default: return 0; // Tables & vectors do not make sense.
} }
#undef FLATBUFFERS_GET #undef FLATBUFFERS_GET
// clang-format on
} }
double GetAnyValueF(reflection::BaseType type, const uint8_t *data) { double GetAnyValueF(reflection::BaseType type, const uint8_t *data) {
@@ -51,8 +53,8 @@ double GetAnyValueF(reflection::BaseType type, const uint8_t *data) {
case reflection::Float: return static_cast<double>(ReadScalar<float>(data)); case reflection::Float: return static_cast<double>(ReadScalar<float>(data));
case reflection::Double: return ReadScalar<double>(data); case reflection::Double: return ReadScalar<double>(data);
case reflection::String: { case reflection::String: {
auto s = reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) + auto s =
data); reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) + data);
return s ? strtod(s->c_str(), nullptr) : 0.0; return s ? strtod(s->c_str(), nullptr) : 0.0;
} }
default: return static_cast<double>(GetAnyValueI(type, data)); default: return static_cast<double>(GetAnyValueI(type, data));
@@ -65,8 +67,8 @@ std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
case reflection::Float: case reflection::Float:
case reflection::Double: return NumToString(GetAnyValueF(type, data)); case reflection::Double: return NumToString(GetAnyValueF(type, data));
case reflection::String: { case reflection::String: {
auto s = reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) + auto s =
data); reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) + data);
return s ? s->c_str() : ""; return s ? s->c_str() : "";
} }
case reflection::Obj: case reflection::Obj:
@@ -105,13 +107,13 @@ std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
} }
case reflection::Vector: case reflection::Vector:
return "[(elements)]"; // TODO: implement this as well. return "[(elements)]"; // TODO: implement this as well.
case reflection::Union: case reflection::Union: return "(union)"; // TODO: implement this as well.
return "(union)"; // TODO: implement this as well.
default: return NumToString(GetAnyValueI(type, data)); default: return NumToString(GetAnyValueI(type, data));
} }
} }
void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val) { void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val) {
// clang-format off
#define FLATBUFFERS_SET(T) WriteScalar(data, static_cast<T>(val)) #define FLATBUFFERS_SET(T) WriteScalar(data, static_cast<T>(val))
switch (type) { switch (type) {
case reflection::UType: case reflection::UType:
@@ -130,6 +132,7 @@ void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val) {
default: break; default: break;
} }
#undef FLATBUFFERS_SET #undef FLATBUFFERS_SET
// clang-format on
} }
void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val) { void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val) {
@@ -165,8 +168,10 @@ class ResizeContext {
ResizeContext(const reflection::Schema &schema, uoffset_t start, int delta, ResizeContext(const reflection::Schema &schema, uoffset_t start, int delta,
std::vector<uint8_t> *flatbuf, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr) const reflection::Object *root_table = nullptr)
: schema_(schema), startptr_(vector_data(*flatbuf) + start), : schema_(schema),
delta_(delta), buf_(*flatbuf), startptr_(vector_data(*flatbuf) + start),
delta_(delta),
buf_(*flatbuf),
dag_check_(flatbuf->size() / sizeof(uoffset_t), false) { dag_check_(flatbuf->size() / sizeof(uoffset_t), false) {
auto mask = static_cast<int>(sizeof(largest_scalar_t) - 1); auto mask = static_cast<int>(sizeof(largest_scalar_t) - 1);
delta_ = (delta_ + mask) & ~mask; delta_ = (delta_ + mask) & ~mask;
@@ -176,16 +181,17 @@ class ResizeContext {
Straddle<uoffset_t, 1>(vector_data(buf_), root, vector_data(buf_)); Straddle<uoffset_t, 1>(vector_data(buf_), root, vector_data(buf_));
ResizeTable(root_table ? *root_table : *schema.root_table(), root); ResizeTable(root_table ? *root_table : *schema.root_table(), root);
// We can now add or remove bytes at start. // We can now add or remove bytes at start.
if (delta_ > 0) buf_.insert(buf_.begin() + start, delta_, 0); if (delta_ > 0)
else buf_.erase(buf_.begin() + start, buf_.begin() + start - delta_); buf_.insert(buf_.begin() + start, delta_, 0);
else
buf_.erase(buf_.begin() + start, buf_.begin() + start - delta_);
} }
// Check if the range between first (lower address) and second straddles // Check if the range between first (lower address) and second straddles
// the insertion point. If it does, change the offset at offsetloc (of // the insertion point. If it does, change the offset at offsetloc (of
// type T, with direction D). // type T, with direction D).
template<typename T, int D> void Straddle(const void *first, template<typename T, int D>
const void *second, void Straddle(const void *first, const void *second, void *offsetloc) {
void *offsetloc) {
if (first <= startptr_ && second >= startptr_) { if (first <= startptr_ && second >= startptr_) {
WriteScalar<T>(offsetloc, ReadScalar<T>(offsetloc) + delta_ * D); WriteScalar<T>(offsetloc, ReadScalar<T>(offsetloc) + delta_ * D);
DagCheck(offsetloc) = true; DagCheck(offsetloc) = true;
@@ -205,8 +211,7 @@ class ResizeContext {
} }
void ResizeTable(const reflection::Object &objectdef, Table *table) { void ResizeTable(const reflection::Object &objectdef, Table *table) {
if (DagCheck(table)) if (DagCheck(table)) return; // Table already visited.
return; // Table already visited.
auto vtable = table->GetVTable(); auto vtable = table->GetVTable();
// Early out: since all fields inside the table must point forwards in // Early out: since all fields inside the table must point forwards in
// memory, if the insertion point is before the table we can stop here. // memory, if the insertion point is before the table we can stop here.
@@ -228,13 +233,14 @@ class ResizeContext {
auto offset = table->GetOptionalFieldOffset(fielddef.offset()); auto offset = table->GetOptionalFieldOffset(fielddef.offset());
if (!offset) continue; if (!offset) continue;
// Ignore structs. // Ignore structs.
auto subobjectdef = base_type == reflection::Obj ? auto subobjectdef =
schema_.objects()->Get(fielddef.type()->index()) : nullptr; base_type == reflection::Obj
? schema_.objects()->Get(fielddef.type()->index())
: nullptr;
if (subobjectdef && subobjectdef->is_struct()) continue; if (subobjectdef && subobjectdef->is_struct()) continue;
// Get this fields' offset, and read it if safe. // Get this fields' offset, and read it if safe.
auto offsetloc = tableloc + offset; auto offsetloc = tableloc + offset;
if (DagCheck(offsetloc)) if (DagCheck(offsetloc)) continue; // This offset already visited.
continue; // This offset already visited.
auto ref = offsetloc + ReadScalar<uoffset_t>(offsetloc); auto ref = offsetloc + ReadScalar<uoffset_t>(offsetloc);
Straddle<uoffset_t, 1>(offsetloc, ref, offsetloc); Straddle<uoffset_t, 1>(offsetloc, ref, offsetloc);
// Recurse. // Recurse.
@@ -248,14 +254,14 @@ class ResizeContext {
if (elem_type != reflection::Obj && elem_type != reflection::String) if (elem_type != reflection::Obj && elem_type != reflection::String)
break; break;
auto vec = reinterpret_cast<Vector<uoffset_t> *>(ref); auto vec = reinterpret_cast<Vector<uoffset_t> *>(ref);
auto elemobjectdef = elem_type == reflection::Obj auto elemobjectdef =
elem_type == reflection::Obj
? schema_.objects()->Get(fielddef.type()->index()) ? schema_.objects()->Get(fielddef.type()->index())
: nullptr; : nullptr;
if (elemobjectdef && elemobjectdef->is_struct()) break; if (elemobjectdef && elemobjectdef->is_struct()) break;
for (uoffset_t i = 0; i < vec->size(); i++) { for (uoffset_t i = 0; i < vec->size(); i++) {
auto loc = vec->Data() + i * sizeof(uoffset_t); auto loc = vec->Data() + i * sizeof(uoffset_t);
if (DagCheck(loc)) if (DagCheck(loc)) continue; // This offset already visited.
continue; // This offset already visited.
auto dest = loc + vec->Get(i); auto dest = loc + vec->Get(i);
Straddle<uoffset_t, 1>(loc, dest, loc); Straddle<uoffset_t, 1>(loc, dest, loc);
if (elemobjectdef) if (elemobjectdef)
@@ -268,10 +274,8 @@ class ResizeContext {
reinterpret_cast<Table *>(ref)); reinterpret_cast<Table *>(ref));
break; break;
} }
case reflection::String: case reflection::String: break;
break; default: assert(false);
default:
assert(false);
} }
} }
// Check if the vtable offset points beyond the insertion point. // Check if the vtable offset points beyond the insertion point.
@@ -317,8 +321,8 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
const reflection::Object *root_table) { const reflection::Object *root_table) {
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(num_elems); auto delta_elem = static_cast<int>(newsize) - static_cast<int>(num_elems);
auto delta_bytes = delta_elem * static_cast<int>(elem_size); auto delta_bytes = delta_elem * static_cast<int>(elem_size);
auto vec_start = reinterpret_cast<const uint8_t *>(vec) - auto vec_start =
vector_data(*flatbuf); reinterpret_cast<const uint8_t *>(vec) - vector_data(*flatbuf);
auto start = static_cast<uoffset_t>(vec_start + sizeof(uoffset_t) + auto start = static_cast<uoffset_t>(vec_start + sizeof(uoffset_t) +
elem_size * num_elems); elem_size * num_elems);
if (delta_bytes) { if (delta_bytes) {
@@ -363,8 +367,7 @@ void CopyInline(FlatBufferBuilder &fbb, const reflection::Field &fielddef,
Offset<const Table *> CopyTable(FlatBufferBuilder &fbb, Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const reflection::Schema &schema, const reflection::Schema &schema,
const reflection::Object &objectdef, const reflection::Object &objectdef,
const Table &table, const Table &table, bool use_string_pooling) {
bool use_string_pooling) {
// Before we can construct the table, we have to first generate any // Before we can construct the table, we have to first generate any
// subobjects, and collect their offsets. // subobjects, and collect their offsets.
std::vector<uoffset_t> offsets; std::vector<uoffset_t> offsets;
@@ -384,22 +387,24 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
case reflection::Obj: { case reflection::Obj: {
auto &subobjectdef = *schema.objects()->Get(fielddef.type()->index()); auto &subobjectdef = *schema.objects()->Get(fielddef.type()->index());
if (!subobjectdef.is_struct()) { if (!subobjectdef.is_struct()) {
offset = CopyTable(fbb, schema, subobjectdef, offset =
*GetFieldT(table, fielddef)).o; CopyTable(fbb, schema, subobjectdef, *GetFieldT(table, fielddef))
.o;
} }
break; break;
} }
case reflection::Union: { case reflection::Union: {
auto &subobjectdef = GetUnionType(schema, objectdef, fielddef, table); auto &subobjectdef = GetUnionType(schema, objectdef, fielddef, table);
offset = CopyTable(fbb, schema, subobjectdef, offset =
*GetFieldT(table, fielddef)).o; CopyTable(fbb, schema, subobjectdef, *GetFieldT(table, fielddef)).o;
break; break;
} }
case reflection::Vector: { case reflection::Vector: {
auto vec = table.GetPointer<const Vector<Offset<Table>> *>( auto vec =
fielddef.offset()); table.GetPointer<const Vector<Offset<Table>> *>(fielddef.offset());
auto element_base_type = fielddef.type()->element(); auto element_base_type = fielddef.type()->element();
auto elemobjectdef = element_base_type == reflection::Obj auto elemobjectdef =
element_base_type == reflection::Obj
? schema.objects()->Get(fielddef.type()->index()) ? schema.objects()->Get(fielddef.type()->index())
: nullptr; : nullptr;
switch (element_base_type) { switch (element_base_type) {
@@ -441,13 +446,10 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
default: // Scalars. default: // Scalars.
break; break;
} }
if (offset) { if (offset) { offsets.push_back(offset); }
offsets.push_back(offset);
}
} }
// Now we can build the actual table from either offsets or scalar data. // Now we can build the actual table from either offsets or scalar data.
auto start = objectdef.is_struct() auto start = objectdef.is_struct() ? fbb.StartStruct(objectdef.minalign())
? fbb.StartStruct(objectdef.minalign())
: fbb.StartTable(); : fbb.StartTable();
size_t offset_idx = 0; size_t offset_idx = 0;
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) { for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
@@ -487,51 +489,40 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
bool VerifyStruct(flatbuffers::Verifier &v, bool VerifyStruct(flatbuffers::Verifier &v,
const flatbuffers::Table &parent_table, const flatbuffers::Table &parent_table,
voffset_t field_offset, voffset_t field_offset, const reflection::Object &obj,
const reflection::Object &obj,
bool required) { bool required) {
auto offset = parent_table.GetOptionalFieldOffset(field_offset); auto offset = parent_table.GetOptionalFieldOffset(field_offset);
if (required && !offset) { if (required && !offset) { return false; }
return false;
}
return !offset || v.Verify(reinterpret_cast<const uint8_t*>(&parent_table) return !offset ||
+ offset, obj.bytesize()); v.Verify(reinterpret_cast<const uint8_t *>(&parent_table) + offset,
obj.bytesize());
} }
bool VerifyVectorOfStructs(flatbuffers::Verifier &v, bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
const flatbuffers::Table &parent_table, const flatbuffers::Table &parent_table,
voffset_t field_offset, voffset_t field_offset,
const reflection::Object &obj, const reflection::Object &obj, bool required) {
bool required) {
auto p = parent_table.GetPointer<const uint8_t *>(field_offset); auto p = parent_table.GetPointer<const uint8_t *>(field_offset);
const uint8_t *end; const uint8_t *end;
if (required && !p) { if (required && !p) { return false; }
return false;
}
return !p || v.VerifyVector(p, obj.bytesize(), &end); return !p || v.VerifyVector(p, obj.bytesize(), &end);
} }
// forward declare to resolve cyclic deps between VerifyObject and VerifyVector // forward declare to resolve cyclic deps between VerifyObject and VerifyVector
bool VerifyObject(flatbuffers::Verifier &v, bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
const reflection::Schema &schema,
const reflection::Object &obj, const reflection::Object &obj,
const flatbuffers::Table *table, const flatbuffers::Table *table, bool isRequired);
bool isRequired);
bool VerifyVector(flatbuffers::Verifier &v, bool VerifyVector(flatbuffers::Verifier &v, const reflection::Schema &schema,
const reflection::Schema &schema,
const flatbuffers::Table &table, const flatbuffers::Table &table,
const reflection::Field &vec_field) { const reflection::Field &vec_field) {
assert(vec_field.type()->base_type() == reflection::Vector); assert(vec_field.type()->base_type() == reflection::Vector);
if (!table.VerifyField<uoffset_t>(v, vec_field.offset())) if (!table.VerifyField<uoffset_t>(v, vec_field.offset())) return false;
return false;
switch (vec_field.type()->element()) { switch (vec_field.type()->element()) {
case reflection::None: case reflection::None: assert(false); break;
assert(false);
break;
case reflection::UType: case reflection::UType:
return v.Verify(flatbuffers::GetFieldV<uint8_t>(table, vec_field)); return v.Verify(flatbuffers::GetFieldV<uint8_t>(table, vec_field));
case reflection::Bool: case reflection::Bool:
@@ -553,17 +544,15 @@ bool VerifyVector(flatbuffers::Verifier &v,
return v.Verify(flatbuffers::GetFieldV<double>(table, vec_field)); return v.Verify(flatbuffers::GetFieldV<double>(table, vec_field));
case reflection::String: { case reflection::String: {
auto vecString = auto vecString =
flatbuffers::GetFieldV<flatbuffers:: flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::String>>(
Offset<flatbuffers::String>>(table, vec_field); table, vec_field);
if (v.Verify(vecString) && v.VerifyVectorOfStrings(vecString)) { if (v.Verify(vecString) && v.VerifyVectorOfStrings(vecString)) {
return true; return true;
} else { } else {
return false; return false;
} }
} }
case reflection::Vector: case reflection::Vector: assert(false); break;
assert(false);
break;
case reflection::Obj: { case reflection::Obj: {
auto obj = schema.objects()->Get(vec_field.type()->index()); auto obj = schema.objects()->Get(vec_field.type()->index());
if (obj->is_struct()) { if (obj->is_struct()) {
@@ -573,10 +562,9 @@ bool VerifyVector(flatbuffers::Verifier &v,
} }
} else { } else {
auto vec = auto vec =
flatbuffers::GetFieldV<flatbuffers:: flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::Table>>(
Offset<flatbuffers::Table>>(table, vec_field); table, vec_field);
if (!v.Verify(vec)) if (!v.Verify(vec)) return false;
return false;
if (vec) { if (vec) {
for (uoffset_t j = 0; j < vec->size(); j++) { for (uoffset_t j = 0; j < vec->size(); j++) {
if (!VerifyObject(v, schema, *obj, vec->Get(j), true)) { if (!VerifyObject(v, schema, *obj, vec->Get(j), true)) {
@@ -587,22 +575,16 @@ bool VerifyVector(flatbuffers::Verifier &v,
} }
return true; return true;
} }
case reflection::Union: case reflection::Union: assert(false); break;
assert(false); default: assert(false); break;
break;
default:
assert(false);
break;
} }
return false; return false;
} }
bool VerifyObject(flatbuffers::Verifier &v, bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
const reflection::Schema &schema,
const reflection::Object &obj, const reflection::Object &obj,
const flatbuffers::Table *table, const flatbuffers::Table *table, bool required) {
bool required) {
if (!table) { if (!table) {
if (!required) if (!required)
return true; return true;
@@ -610,47 +592,37 @@ bool VerifyObject(flatbuffers::Verifier &v,
return false; return false;
} }
if (!table->VerifyTableStart(v)) if (!table->VerifyTableStart(v)) return false;
return false;
for (uoffset_t i = 0; i < obj.fields()->size(); i++) { for (uoffset_t i = 0; i < obj.fields()->size(); i++) {
auto field_def = obj.fields()->Get(i); auto field_def = obj.fields()->Get(i);
switch (field_def->type()->base_type()) { switch (field_def->type()->base_type()) {
case reflection::None: case reflection::None: assert(false); break;
assert(false);
break;
case reflection::UType: case reflection::UType:
if (!table->VerifyField<uint8_t>(v, field_def->offset())) if (!table->VerifyField<uint8_t>(v, field_def->offset())) return false;
return false;
break; break;
case reflection::Bool: case reflection::Bool:
case reflection::Byte: case reflection::Byte:
case reflection::UByte: case reflection::UByte:
if (!table->VerifyField<int8_t>(v, field_def->offset())) if (!table->VerifyField<int8_t>(v, field_def->offset())) return false;
return false;
break; break;
case reflection::Short: case reflection::Short:
case reflection::UShort: case reflection::UShort:
if (!table->VerifyField<int16_t>(v, field_def->offset())) if (!table->VerifyField<int16_t>(v, field_def->offset())) return false;
return false;
break; break;
case reflection::Int: case reflection::Int:
case reflection::UInt: case reflection::UInt:
if (!table->VerifyField<int32_t>(v, field_def->offset())) if (!table->VerifyField<int32_t>(v, field_def->offset())) return false;
return false;
break; break;
case reflection::Long: case reflection::Long:
case reflection::ULong: case reflection::ULong:
if (!table->VerifyField<int64_t>(v, field_def->offset())) if (!table->VerifyField<int64_t>(v, field_def->offset())) return false;
return false;
break; break;
case reflection::Float: case reflection::Float:
if (!table->VerifyField<float>(v, field_def->offset())) if (!table->VerifyField<float>(v, field_def->offset())) return false;
return false;
break; break;
case reflection::Double: case reflection::Double:
if (!table->VerifyField<double>(v, field_def->offset())) if (!table->VerifyField<double>(v, field_def->offset())) return false;
return false;
break; break;
case reflection::String: case reflection::String:
if (!table->VerifyField<uoffset_t>(v, field_def->offset()) || if (!table->VerifyField<uoffset_t>(v, field_def->offset()) ||
@@ -659,8 +631,7 @@ bool VerifyObject(flatbuffers::Verifier &v,
} }
break; break;
case reflection::Vector: case reflection::Vector:
if (!VerifyVector(v, schema, *table, *field_def)) if (!VerifyVector(v, schema, *table, *field_def)) return false;
return false;
break; break;
case reflection::Obj: { case reflection::Obj: {
auto child_obj = schema.objects()->Get(field_def->type()->index()); auto child_obj = schema.objects()->Get(field_def->type()->index());
@@ -694,22 +665,17 @@ bool VerifyObject(flatbuffers::Verifier &v,
} }
break; break;
} }
default: default: assert(false); break;
assert(false);
break;
} }
} }
if (!v.EndTable()) if (!v.EndTable()) return false;
return false;
return true; return true;
} }
bool Verify(const reflection::Schema &schema, bool Verify(const reflection::Schema &schema, const reflection::Object &root,
const reflection::Object &root, const uint8_t *buf, size_t length) {
const uint8_t *buf,
size_t length) {
Verifier v(buf, length); Verifier v(buf, length);
return VerifyObject(v, schema, root, flatbuffers::GetAnyRoot(buf), true); return VerifyObject(v, schema, root, flatbuffers::GetAnyRoot(buf), true);
} }

View File

@@ -57,6 +57,7 @@ bool FileExists(const char *name) {
} }
bool DirExists(const char *name) { bool DirExists(const char *name) {
// clang-format off
#ifdef _WIN32 #ifdef _WIN32
#define flatbuffers_stat _stat #define flatbuffers_stat _stat
#define FLATBUFFERS_S_IFDIR _S_IFDIR #define FLATBUFFERS_S_IFDIR _S_IFDIR
@@ -64,6 +65,7 @@ bool DirExists(const char *name) {
#define flatbuffers_stat stat #define flatbuffers_stat stat
#define FLATBUFFERS_S_IFDIR S_IFDIR #define FLATBUFFERS_S_IFDIR S_IFDIR
#endif #endif
// clang-format on
struct flatbuffers_stat file_info; struct flatbuffers_stat file_info;
if (flatbuffers_stat(name, &file_info) != 0) return false; if (flatbuffers_stat(name, &file_info) != 0) return false;
return (file_info.st_mode & FLATBUFFERS_S_IFDIR) != 0; return (file_info.st_mode & FLATBUFFERS_S_IFDIR) != 0;
@@ -78,8 +80,8 @@ LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function) {
FileExistsFunction SetFileExistsFunction( FileExistsFunction SetFileExistsFunction(
FileExistsFunction file_exists_function) { FileExistsFunction file_exists_function) {
FileExistsFunction previous_function = g_file_exists_function; FileExistsFunction previous_function = g_file_exists_function;
g_file_exists_function = file_exists_function ? g_file_exists_function =
file_exists_function : FileExistsRaw; file_exists_function ? file_exists_function : FileExistsRaw;
return previous_function; return previous_function;
} }

View File

@@ -27,44 +27,36 @@ std::unique_ptr< MonsterStorage::Stub> MonsterStorage::NewStub(const std::shared
} }
MonsterStorage::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) MonsterStorage::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel)
: channel_(channel) , rpcmethod_Store_(MonsterStorage_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) : channel_(channel) , rpcmethod_Store_(MonsterStorage_method_names[0], ::grpc::RpcMethod::NORMAL_RPC, channel)
, rpcmethod_Retrieve_(MonsterStorage_method_names[1], ::grpc::internal::RpcMethod::SERVER_STREAMING, channel) , rpcmethod_Retrieve_(MonsterStorage_method_names[1], ::grpc::RpcMethod::SERVER_STREAMING, channel)
{} {}
::grpc::Status MonsterStorage::Stub::Store(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, flatbuffers::grpc::Message<Stat>* response) { ::grpc::Status MonsterStorage::Stub::Store(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, flatbuffers::grpc::Message<Stat>* response) {
return ::grpc::internal::BlockingUnaryCall(channel_.get(), rpcmethod_Store_, context, request, response); return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_Store_, context, request, response);
} }
::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>* MonsterStorage::Stub::AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) { ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>* MonsterStorage::Stub::AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) {
return ::grpc::internal::ClientAsyncResponseReaderFactory< flatbuffers::grpc::Message<Stat>>::Create(channel_.get(), cq, rpcmethod_Store_, context, request, true); return ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>::Create(channel_.get(), cq, rpcmethod_Store_, context, request);
}
::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>* MonsterStorage::Stub::PrepareAsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) {
return ::grpc::internal::ClientAsyncResponseReaderFactory< flatbuffers::grpc::Message<Stat>>::Create(channel_.get(), cq, rpcmethod_Store_, context, request, false);
} }
::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>* MonsterStorage::Stub::RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) { ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>* MonsterStorage::Stub::RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) {
return ::grpc::internal::ClientReaderFactory< flatbuffers::grpc::Message<Monster>>::Create(channel_.get(), rpcmethod_Retrieve_, context, request); return new ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>(channel_.get(), rpcmethod_Retrieve_, context, request);
} }
::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>* MonsterStorage::Stub::AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) { ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>* MonsterStorage::Stub::AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) {
return ::grpc::internal::ClientAsyncReaderFactory< flatbuffers::grpc::Message<Monster>>::Create(channel_.get(), cq, rpcmethod_Retrieve_, context, request, true, tag); return ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>::Create(channel_.get(), cq, rpcmethod_Retrieve_, context, request, tag);
}
::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>* MonsterStorage::Stub::PrepareAsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq) {
return ::grpc::internal::ClientAsyncReaderFactory< flatbuffers::grpc::Message<Monster>>::Create(channel_.get(), cq, rpcmethod_Retrieve_, context, request, false, nullptr);
} }
MonsterStorage::Service::Service() { MonsterStorage::Service::Service() {
AddMethod(new ::grpc::internal::RpcServiceMethod( AddMethod(new ::grpc::RpcServiceMethod(
MonsterStorage_method_names[0], MonsterStorage_method_names[0],
::grpc::internal::RpcMethod::NORMAL_RPC, ::grpc::RpcMethod::NORMAL_RPC,
new ::grpc::internal::RpcMethodHandler< MonsterStorage::Service, flatbuffers::grpc::Message<Monster>, flatbuffers::grpc::Message<Stat>>( new ::grpc::RpcMethodHandler< MonsterStorage::Service, flatbuffers::grpc::Message<Monster>, flatbuffers::grpc::Message<Stat>>(
std::mem_fn(&MonsterStorage::Service::Store), this))); std::mem_fn(&MonsterStorage::Service::Store), this)));
AddMethod(new ::grpc::internal::RpcServiceMethod( AddMethod(new ::grpc::RpcServiceMethod(
MonsterStorage_method_names[1], MonsterStorage_method_names[1],
::grpc::internal::RpcMethod::SERVER_STREAMING, ::grpc::RpcMethod::SERVER_STREAMING,
new ::grpc::internal::ServerStreamingHandler< MonsterStorage::Service, flatbuffers::grpc::Message<Stat>, flatbuffers::grpc::Message<Monster>>( new ::grpc::ServerStreamingHandler< MonsterStorage::Service, flatbuffers::grpc::Message<Stat>, flatbuffers::grpc::Message<Monster>>(
std::mem_fn(&MonsterStorage::Service::Retrieve), this))); std::mem_fn(&MonsterStorage::Service::Retrieve), this)));
} }

View File

@@ -4,8 +4,8 @@
#ifndef GRPC_monster_5ftest__INCLUDED #ifndef GRPC_monster_5ftest__INCLUDED
#define GRPC_monster_5ftest__INCLUDED #define GRPC_monster_5ftest__INCLUDED
#include "monster_test_generated.h"
#include "flatbuffers/grpc.h" #include "flatbuffers/grpc.h"
#include "monster_test_generated.h"
#include <grpc++/impl/codegen/async_stream.h> #include <grpc++/impl/codegen/async_stream.h>
#include <grpc++/impl/codegen/async_unary_call.h> #include <grpc++/impl/codegen/async_unary_call.h>
@@ -20,6 +20,7 @@
namespace grpc { namespace grpc {
class CompletionQueue; class CompletionQueue;
class Channel; class Channel;
class RpcService;
class ServerCompletionQueue; class ServerCompletionQueue;
class ServerContext; class ServerContext;
} // namespace grpc } // namespace grpc
@@ -39,24 +40,16 @@ class MonsterStorage final {
std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) { std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) {
return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>>(AsyncStoreRaw(context, request, cq)); return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>>(AsyncStoreRaw(context, request, cq));
} }
std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>> PrepareAsyncStore(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) {
return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>>(PrepareAsyncStoreRaw(context, request, cq));
}
std::unique_ptr< ::grpc::ClientReaderInterface< flatbuffers::grpc::Message<Monster>>> Retrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) { std::unique_ptr< ::grpc::ClientReaderInterface< flatbuffers::grpc::Message<Monster>>> Retrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) {
return std::unique_ptr< ::grpc::ClientReaderInterface< flatbuffers::grpc::Message<Monster>>>(RetrieveRaw(context, request)); return std::unique_ptr< ::grpc::ClientReaderInterface< flatbuffers::grpc::Message<Monster>>>(RetrieveRaw(context, request));
} }
std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) { std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) {
return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>>(AsyncRetrieveRaw(context, request, cq, tag)); return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>>(AsyncRetrieveRaw(context, request, cq, tag));
} }
std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>> PrepareAsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq) {
return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>>(PrepareAsyncRetrieveRaw(context, request, cq));
}
private: private:
virtual ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) = 0;
virtual ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>* PrepareAsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) = 0;
virtual ::grpc::ClientReaderInterface< flatbuffers::grpc::Message<Monster>>* RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) = 0; virtual ::grpc::ClientReaderInterface< flatbuffers::grpc::Message<Monster>>* RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) = 0;
virtual ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) = 0; virtual ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) = 0;
virtual ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>* PrepareAsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq) = 0;
}; };
class Stub final : public StubInterface { class Stub final : public StubInterface {
public: public:
@@ -65,28 +58,20 @@ class MonsterStorage final {
std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) { std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) {
return std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>>(AsyncStoreRaw(context, request, cq)); return std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>>(AsyncStoreRaw(context, request, cq));
} }
std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>> PrepareAsyncStore(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) {
return std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>>(PrepareAsyncStoreRaw(context, request, cq));
}
std::unique_ptr< ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>> Retrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) { std::unique_ptr< ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>> Retrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) {
return std::unique_ptr< ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>>(RetrieveRaw(context, request)); return std::unique_ptr< ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>>(RetrieveRaw(context, request));
} }
std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) { std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) {
return std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>>(AsyncRetrieveRaw(context, request, cq, tag)); return std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>>(AsyncRetrieveRaw(context, request, cq, tag));
} }
std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>> PrepareAsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq) {
return std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>>(PrepareAsyncRetrieveRaw(context, request, cq));
}
private: private:
std::shared_ptr< ::grpc::ChannelInterface> channel_; std::shared_ptr< ::grpc::ChannelInterface> channel_;
::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) override;
::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>* PrepareAsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) override;
::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>* RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) override; ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>* RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) override;
::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) override; ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) override;
::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>* PrepareAsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq) override; const ::grpc::RpcMethod rpcmethod_Store_;
const ::grpc::internal::RpcMethod rpcmethod_Store_; const ::grpc::RpcMethod rpcmethod_Retrieve_;
const ::grpc::internal::RpcMethod rpcmethod_Retrieve_;
}; };
static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
@@ -179,7 +164,7 @@ class MonsterStorage final {
public: public:
WithStreamedUnaryMethod_Store() { WithStreamedUnaryMethod_Store() {
::grpc::Service::MarkMethodStreamed(0, ::grpc::Service::MarkMethodStreamed(0,
new ::grpc::internal::StreamedUnaryHandler< flatbuffers::grpc::Message<Monster>, flatbuffers::grpc::Message<Stat>>(std::bind(&WithStreamedUnaryMethod_Store<BaseClass>::StreamedStore, this, std::placeholders::_1, std::placeholders::_2))); new ::grpc::StreamedUnaryHandler< flatbuffers::grpc::Message<Monster>, flatbuffers::grpc::Message<Stat>>(std::bind(&WithStreamedUnaryMethod_Store<BaseClass>::StreamedStore, this, std::placeholders::_1, std::placeholders::_2)));
} }
~WithStreamedUnaryMethod_Store() override { ~WithStreamedUnaryMethod_Store() override {
BaseClassMustBeDerivedFromService(this); BaseClassMustBeDerivedFromService(this);
@@ -200,7 +185,7 @@ class MonsterStorage final {
public: public:
WithSplitStreamingMethod_Retrieve() { WithSplitStreamingMethod_Retrieve() {
::grpc::Service::MarkMethodStreamed(1, ::grpc::Service::MarkMethodStreamed(1,
new ::grpc::internal::SplitServerStreamingHandler< flatbuffers::grpc::Message<Stat>, flatbuffers::grpc::Message<Monster>>(std::bind(&WithSplitStreamingMethod_Retrieve<BaseClass>::StreamedRetrieve, this, std::placeholders::_1, std::placeholders::_2))); new ::grpc::SplitServerStreamingHandler< flatbuffers::grpc::Message<Stat>, flatbuffers::grpc::Message<Monster>>(std::bind(&WithSplitStreamingMethod_Retrieve<BaseClass>::StreamedRetrieve, this, std::placeholders::_1, std::placeholders::_2)));
} }
~WithSplitStreamingMethod_Retrieve() override { ~WithSplitStreamingMethod_Retrieve() override {
BaseClassMustBeDerivedFromService(this); BaseClassMustBeDerivedFromService(this);

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ export class TableInNestedNS {
/** /**
* @type {flatbuffers.ByteBuffer} * @type {flatbuffers.ByteBuffer}
*/ */
bb: flatbuffers.ByteBuffer|null = null; bb: flatbuffers.ByteBuffer;
/** /**
* @type {number} * @type {number}
@@ -48,8 +48,8 @@ static getRootAsTableInNestedNS(bb:flatbuffers.ByteBuffer, obj?:TableInNestedNS)
* @returns {number} * @returns {number}
*/ */
foo():number { foo():number {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; return offset ? this.bb.readInt32(this.bb_pos + offset) : 0;
}; };
/** /**
@@ -57,13 +57,13 @@ foo():number {
* @returns {boolean} * @returns {boolean}
*/ */
mutate_foo(value:number):boolean { mutate_foo(value:number):boolean {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
if (offset === 0) { if (offset === 0) {
return false; return false;
} }
this.bb!.writeInt32(this.bb_pos + offset, value); this.bb.writeInt32(this.bb_pos + offset, value);
return true; return true;
}; };
@@ -101,7 +101,7 @@ export class StructInNestedNS {
/** /**
* @type {flatbuffers.ByteBuffer} * @type {flatbuffers.ByteBuffer}
*/ */
bb: flatbuffers.ByteBuffer|null = null; bb: flatbuffers.ByteBuffer;
/** /**
* @type {number} * @type {number}
@@ -122,7 +122,7 @@ __init(i:number, bb:flatbuffers.ByteBuffer):StructInNestedNS {
* @returns {number} * @returns {number}
*/ */
a():number { a():number {
return this.bb!.readInt32(this.bb_pos); return this.bb.readInt32(this.bb_pos);
}; };
/** /**
@@ -130,13 +130,13 @@ a():number {
* @returns {boolean} * @returns {boolean}
*/ */
mutate_a(value:number):boolean { mutate_a(value:number):boolean {
var offset = this.bb!.__offset(this.bb_pos, 0); var offset = this.bb.__offset(this.bb_pos, 0);
if (offset === 0) { if (offset === 0) {
return false; return false;
} }
this.bb!.writeInt32(this.bb_pos + offset, value); this.bb.writeInt32(this.bb_pos + offset, value);
return true; return true;
}; };
@@ -144,7 +144,7 @@ mutate_a(value:number):boolean {
* @returns {number} * @returns {number}
*/ */
b():number { b():number {
return this.bb!.readInt32(this.bb_pos + 4); return this.bb.readInt32(this.bb_pos + 4);
}; };
/** /**
@@ -152,13 +152,13 @@ b():number {
* @returns {boolean} * @returns {boolean}
*/ */
mutate_b(value:number):boolean { mutate_b(value:number):boolean {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
if (offset === 0) { if (offset === 0) {
return false; return false;
} }
this.bb!.writeInt32(this.bb_pos + offset, value); this.bb.writeInt32(this.bb_pos + offset, value);
return true; return true;
}; };

View File

@@ -9,7 +9,7 @@ export class TableInFirstNS {
/** /**
* @type {flatbuffers.ByteBuffer} * @type {flatbuffers.ByteBuffer}
*/ */
bb: flatbuffers.ByteBuffer|null = null; bb: flatbuffers.ByteBuffer;
/** /**
* @type {number} * @type {number}
@@ -40,16 +40,16 @@ static getRootAsTableInFirstNS(bb:flatbuffers.ByteBuffer, obj?:TableInFirstNS):T
* @returns {NamespaceA.NamespaceB.TableInNestedNS|null} * @returns {NamespaceA.NamespaceB.TableInNestedNS|null}
*/ */
fooTable(obj?:NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS):NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS|null { fooTable(obj?:NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS):NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS|null {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? (obj || new NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; return offset ? (obj || new NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
}; };
/** /**
* @returns {NamespaceA.NamespaceB.EnumInNestedNS} * @returns {NamespaceA.NamespaceB.EnumInNestedNS}
*/ */
fooEnum():NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS { fooEnum():NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS {
var offset = this.bb!.__offset(this.bb_pos, 6); var offset = this.bb.__offset(this.bb_pos, 6);
return offset ? /** @type {NamespaceA.NamespaceB.EnumInNestedNS} */ (this.bb!.readInt8(this.bb_pos + offset)) : NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS.A; return offset ? /** @type {NamespaceA.NamespaceB.EnumInNestedNS} */ (this.bb.readInt8(this.bb_pos + offset)) : NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS.A;
}; };
/** /**
@@ -57,13 +57,13 @@ fooEnum():NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS {
* @returns {boolean} * @returns {boolean}
*/ */
mutate_foo_enum(value:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS):boolean { mutate_foo_enum(value:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS):boolean {
var offset = this.bb!.__offset(this.bb_pos, 6); var offset = this.bb.__offset(this.bb_pos, 6);
if (offset === 0) { if (offset === 0) {
return false; return false;
} }
this.bb!.writeInt8(this.bb_pos + offset, value); this.bb.writeInt8(this.bb_pos + offset, value);
return true; return true;
}; };
@@ -72,8 +72,8 @@ mutate_foo_enum(value:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS
* @returns {NamespaceA.NamespaceB.StructInNestedNS|null} * @returns {NamespaceA.NamespaceB.StructInNestedNS|null}
*/ */
fooStruct(obj?:NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS):NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS|null { fooStruct(obj?:NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS):NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS|null {
var offset = this.bb!.__offset(this.bb_pos, 8); var offset = this.bb.__offset(this.bb_pos, 8);
return offset ? (obj || new NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS).__init(this.bb_pos + offset, this.bb!) : null; return offset ? (obj || new NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS).__init(this.bb_pos + offset, this.bb) : null;
}; };
/** /**
@@ -126,7 +126,7 @@ export class TableInC {
/** /**
* @type {flatbuffers.ByteBuffer} * @type {flatbuffers.ByteBuffer}
*/ */
bb: flatbuffers.ByteBuffer|null = null; bb: flatbuffers.ByteBuffer;
/** /**
* @type {number} * @type {number}
@@ -157,8 +157,8 @@ static getRootAsTableInC(bb:flatbuffers.ByteBuffer, obj?:TableInC):TableInC {
* @returns {NamespaceA.TableInFirstNS|null} * @returns {NamespaceA.TableInFirstNS|null}
*/ */
referToA1(obj?:NamespaceA.TableInFirstNS):NamespaceA.TableInFirstNS|null { referToA1(obj?:NamespaceA.TableInFirstNS):NamespaceA.TableInFirstNS|null {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? (obj || new NamespaceA.TableInFirstNS).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; return offset ? (obj || new NamespaceA.TableInFirstNS).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
}; };
/** /**
@@ -166,8 +166,8 @@ referToA1(obj?:NamespaceA.TableInFirstNS):NamespaceA.TableInFirstNS|null {
* @returns {NamespaceA.SecondTableInA|null} * @returns {NamespaceA.SecondTableInA|null}
*/ */
referToA2(obj?:NamespaceA.SecondTableInA):NamespaceA.SecondTableInA|null { referToA2(obj?:NamespaceA.SecondTableInA):NamespaceA.SecondTableInA|null {
var offset = this.bb!.__offset(this.bb_pos, 6); var offset = this.bb.__offset(this.bb_pos, 6);
return offset ? (obj || new NamespaceA.SecondTableInA).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; return offset ? (obj || new NamespaceA.SecondTableInA).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
}; };
/** /**
@@ -212,7 +212,7 @@ export class SecondTableInA {
/** /**
* @type {flatbuffers.ByteBuffer} * @type {flatbuffers.ByteBuffer}
*/ */
bb: flatbuffers.ByteBuffer|null = null; bb: flatbuffers.ByteBuffer;
/** /**
* @type {number} * @type {number}
@@ -243,8 +243,8 @@ static getRootAsSecondTableInA(bb:flatbuffers.ByteBuffer, obj?:SecondTableInA):S
* @returns {NamespaceC.TableInC|null} * @returns {NamespaceC.TableInC|null}
*/ */
referToC(obj?:NamespaceC.TableInC):NamespaceC.TableInC|null { referToC(obj?:NamespaceC.TableInC):NamespaceC.TableInC|null {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? (obj || new NamespaceC.TableInC).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; return offset ? (obj || new NamespaceC.TableInC).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
}; };
/** /**

View File

@@ -16,15 +16,16 @@
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h" #include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "flatbuffers/registry.h"
#include "flatbuffers/minireflect.h" #include "flatbuffers/minireflect.h"
#include "flatbuffers/registry.h"
#include "flatbuffers/util.h"
#include "monster_test_generated.h" #include "monster_test_generated.h"
#include "namespace_test/namespace_test1_generated.h" #include "namespace_test/namespace_test1_generated.h"
#include "namespace_test/namespace_test2_generated.h" #include "namespace_test/namespace_test2_generated.h"
#include "union_vector/union_vector_generated.h" #include "union_vector/union_vector_generated.h"
// clang-format off
#ifndef FLATBUFFERS_CPP98_STL #ifndef FLATBUFFERS_CPP98_STL
#include <random> #include <random>
#endif #endif
@@ -42,6 +43,7 @@ using namespace MyGame::Example;
#define TEST_OUTPUT_LINE(...) \ #define TEST_OUTPUT_LINE(...) \
{ printf(__VA_ARGS__); printf("\n"); } { printf(__VA_ARGS__); printf("\n"); }
#endif #endif
// clang-format on
int testing_fails = 0; int testing_fails = 0;
@@ -56,17 +58,14 @@ void TestFail(const char *expval, const char *val, const char *exp,
void TestEqStr(const char *expval, const char *val, const char *exp, void TestEqStr(const char *expval, const char *val, const char *exp,
const char *file, int line) { const char *file, int line) {
if (strcmp(expval, val) != 0) { if (strcmp(expval, val) != 0) { TestFail(expval, val, exp, file, line); }
TestFail(expval, val, exp, file, line);
}
} }
template<typename T, typename U> template<typename T, typename U>
void TestEq(T expval, U val, const char *exp, const char *file, int line) { void TestEq(T expval, U val, const char *exp, const char *file, int line) {
if (U(expval) != val) { if (U(expval) != val) {
TestFail(flatbuffers::NumToString(expval).c_str(), TestFail(flatbuffers::NumToString(expval).c_str(),
flatbuffers::NumToString(val).c_str(), flatbuffers::NumToString(val).c_str(), exp, file, line);
exp, file, line);
} }
} }
@@ -105,7 +104,7 @@ flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) {
Test tests[] = { Test(10, 20), Test(30, 40) }; Test tests[] = { Test(10, 20), Test(30, 40) };
auto testv = builder.CreateVectorOfStructs(tests, 2); auto testv = builder.CreateVectorOfStructs(tests, 2);
// clang-format off
#ifndef FLATBUFFERS_CPP98_STL #ifndef FLATBUFFERS_CPP98_STL
// Create a vector of structures from a lambda. // Create a vector of structures from a lambda.
auto testv2 = builder.CreateVectorOfStructs<Test>( auto testv2 = builder.CreateVectorOfStructs<Test>(
@@ -119,6 +118,7 @@ flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) {
*s = (reinterpret_cast<Test*>(state))[i]; *s = (reinterpret_cast<Test*>(state))[i];
}, tests); }, tests);
#endif // FLATBUFFERS_CPP98_STL #endif // FLATBUFFERS_CPP98_STL
// clang-format on
// create monster with very few fields set: // create monster with very few fields set:
// (same functionality as CreateMonster below, but sets fields manually) // (same functionality as CreateMonster below, but sets fields manually)
@@ -139,12 +139,14 @@ flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) {
// Create an array of strings. Also test string pooling, and lambdas. // Create an array of strings. Also test string pooling, and lambdas.
auto vecofstrings = auto vecofstrings =
builder.CreateVector<flatbuffers::Offset<flatbuffers::String>>(4, builder.CreateVector<flatbuffers::Offset<flatbuffers::String>>(
4,
[](size_t i, flatbuffers::FlatBufferBuilder *b) [](size_t i, flatbuffers::FlatBufferBuilder *b)
-> flatbuffers::Offset<flatbuffers::String> { -> flatbuffers::Offset<flatbuffers::String> {
static const char *names[] = { "bob", "fred", "bob", "fred" }; static const char *names[] = { "bob", "fred", "bob", "fred" };
return b->CreateSharedString(names[i]); return b->CreateSharedString(names[i]);
}, &builder); },
&builder);
// Creating vectors of strings in one convenient call. // Creating vectors of strings in one convenient call.
std::vector<std::string> names2; std::vector<std::string> names2;
@@ -182,9 +184,8 @@ flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) {
// If for whatever reason you don't have the nested_builder available, you // If for whatever reason you don't have the nested_builder available, you
// can substitute flatbuffers::largest_scalar_t (64-bit) for the alignment, or // can substitute flatbuffers::largest_scalar_t (64-bit) for the alignment, or
// the largest force_align value in your schema if you're using it. // the largest force_align value in your schema if you're using it.
auto nested_flatbuffer_vector = auto nested_flatbuffer_vector = builder.CreateVector(
builder.CreateVector(nested_builder.GetBufferPointer(), nested_builder.GetBufferPointer(), nested_builder.GetSize());
nested_builder.GetSize());
// Test a nested FlexBuffer: // Test a nested FlexBuffer:
flexbuffers::Builder flexbuild; flexbuffers::Builder flexbuild;
@@ -196,18 +197,20 @@ flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) {
auto mloc = CreateMonster(builder, &vec, 150, 80, name, inventory, Color_Blue, auto mloc = CreateMonster(builder, &vec, 150, 80, name, inventory, Color_Blue,
Any_Monster, mlocs[1].Union(), // Store a union. Any_Monster, mlocs[1].Union(), // Store a union.
testv, vecofstrings, vecoftables, 0, testv, vecofstrings, vecoftables, 0,
nested_flatbuffer_vector, 0, false, nested_flatbuffer_vector, 0, false, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 3.14159f, 3.0f, 0.0f, 0, 0, 0, 0, 3.14159f, 3.0f, 0.0f, vecofstrings2,
vecofstrings2, vecofstructs, flex, testv2); vecofstructs, flex, testv2);
FinishMonsterBuffer(builder, mloc); FinishMonsterBuffer(builder, mloc);
// clang-format off
#ifdef FLATBUFFERS_TEST_VERBOSE #ifdef FLATBUFFERS_TEST_VERBOSE
// print byte data for debugging: // print byte data for debugging:
auto p = builder.GetBufferPointer(); auto p = builder.GetBufferPointer();
for (flatbuffers::uoffset_t i = 0; i < builder.GetSize(); i++) for (flatbuffers::uoffset_t i = 0; i < builder.GetSize(); i++)
printf("%d ", p[i]); printf("%d ", p[i]);
#endif #endif
// clang-format on
// return the buffer for the caller to use. // return the buffer for the caller to use.
auto bufferpointer = auto bufferpointer =
@@ -220,7 +223,6 @@ flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) {
// example of accessing a buffer loaded in memory: // example of accessing a buffer loaded in memory:
void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length, void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length,
bool pooled = true) { bool pooled = true) {
// First, verify the buffers integrity (optional) // First, verify the buffers integrity (optional)
flatbuffers::Verifier verifier(flatbuf, length); flatbuffers::Verifier verifier(flatbuf, length);
TEST_EQ(VerifyMonsterBuffer(verifier), true); TEST_EQ(VerifyMonsterBuffer(verifier), true);
@@ -313,7 +315,8 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length,
TEST_EQ(true, (left->KeyCompareLessThan(right))); TEST_EQ(true, (left->KeyCompareLessThan(right)));
} }
TEST_NOTNULL(vecofstructs->LookupByKey(3)); TEST_NOTNULL(vecofstructs->LookupByKey(3));
TEST_EQ(static_cast<const Ability*>(nullptr), vecofstructs->LookupByKey(5)); TEST_EQ(static_cast<const Ability *>(nullptr),
vecofstructs->LookupByKey(5));
} }
// Test nested FlatBuffers if available: // Test nested FlatBuffers if available:
@@ -388,7 +391,8 @@ void MutateFlatBuffersTest(uint8_t *flatbuf, std::size_t length) {
// Monster originally at 150 mana (default value) // Monster originally at 150 mana (default value)
auto mana_default_ok = monster->mutate_mana(150); // Mutate to default value. auto mana_default_ok = monster->mutate_mana(150); // Mutate to default value.
TEST_EQ(mana_default_ok, true); // Mutation should succeed, because default value. TEST_EQ(mana_default_ok,
true); // Mutation should succeed, because default value.
TEST_EQ(monster->mana(), 150); TEST_EQ(monster->mana(), 150);
auto mana_ok = monster->mutate_mana(10); auto mana_ok = monster->mutate_mana(10);
TEST_EQ(mana_ok, false); // Field was NOT present, because default value. TEST_EQ(mana_ok, false); // Field was NOT present, because default value.
@@ -454,8 +458,7 @@ void ObjectFlatBuffersTest(uint8_t *flatbuf) {
auto len1 = fbb1.GetSize(); auto len1 = fbb1.GetSize();
auto len2 = fbb2.GetSize(); auto len2 = fbb2.GetSize();
TEST_EQ(len1, len2); TEST_EQ(len1, len2);
TEST_EQ(memcmp(fbb1.GetBufferPointer(), fbb2.GetBufferPointer(), TEST_EQ(memcmp(fbb1.GetBufferPointer(), fbb2.GetBufferPointer(), len1), 0);
len1), 0);
// Test it with the original buffer test to make sure all data survived. // Test it with the original buffer test to make sure all data survived.
AccessFlatBufferTest(fbb2.GetBufferPointer(), len2, false); AccessFlatBufferTest(fbb2.GetBufferPointer(), len2, false);
@@ -511,8 +514,8 @@ void ObjectFlatBuffersTest(uint8_t *flatbuf) {
void SizePrefixedTest() { void SizePrefixedTest() {
// Create size prefixed buffer. // Create size prefixed buffer.
flatbuffers::FlatBufferBuilder fbb; flatbuffers::FlatBufferBuilder fbb;
fbb.FinishSizePrefixed(CreateMonster(fbb, 0, 200, 300, fbb.FinishSizePrefixed(
fbb.CreateString("bob"))); CreateMonster(fbb, 0, 200, 300, fbb.CreateString("bob")));
// Verify it. // Verify it.
flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize()); flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
@@ -526,8 +529,8 @@ void SizePrefixedTest() {
TEST_EQ_STR(m->name()->c_str(), "bob"); TEST_EQ_STR(m->name()->c_str(), "bob");
} }
void TriviallyCopyableTest() { void TriviallyCopyableTest() {
// clang-format off
#if __GNUG__ && __GNUC__ < 5 #if __GNUG__ && __GNUC__ < 5
TEST_EQ(__has_trivial_copy(Vec3), true); TEST_EQ(__has_trivial_copy(Vec3), true);
#else #else
@@ -535,28 +538,29 @@ void TriviallyCopyableTest() {
TEST_EQ(std::is_trivially_copyable<Vec3>::value, true); TEST_EQ(std::is_trivially_copyable<Vec3>::value, true);
#endif #endif
#endif #endif
// clang-format on
} }
// example of parsing text straight into a buffer, and generating // example of parsing text straight into a buffer, and generating
// text back from it: // text back from it:
void ParseAndGenerateTextTest() { void ParseAndGenerateTextTest() {
// load FlatBuffer schema (.fbs) and JSON from disk // load FlatBuffer schema (.fbs) and JSON from disk
std::string schemafile; std::string schemafile;
std::string jsonfile; std::string jsonfile;
TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_test.fbs").c_str(),
false, &schemafile),
true);
TEST_EQ(flatbuffers::LoadFile( TEST_EQ(flatbuffers::LoadFile(
(test_data_path + "monster_test.fbs").c_str(), false, &schemafile), true); (test_data_path + "monsterdata_test.golden").c_str(), false,
TEST_EQ(flatbuffers::LoadFile( &jsonfile),
(test_data_path + "monsterdata_test.golden").c_str(), false, &jsonfile),
true); true);
// parse schema first, so we can use it to parse the data after // parse schema first, so we can use it to parse the data after
flatbuffers::Parser parser; flatbuffers::Parser parser;
auto include_test_path = auto include_test_path =
flatbuffers::ConCatPathFileName(test_data_path, "include_test"); flatbuffers::ConCatPathFileName(test_data_path, "include_test");
const char *include_directories[] = { const char *include_directories[] = { test_data_path.c_str(),
test_data_path.c_str(), include_test_path.c_str(), nullptr include_test_path.c_str(), nullptr };
};
TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true); TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
TEST_EQ(parser.Parse(jsonfile.c_str(), include_directories), true); TEST_EQ(parser.Parse(jsonfile.c_str(), include_directories), true);
@@ -573,7 +577,8 @@ void ParseAndGenerateTextTest() {
// to ensure it is correct, we now generate text back from the binary, // to ensure it is correct, we now generate text back from the binary,
// and compare the two: // and compare the two:
std::string jsongen; std::string jsongen;
auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result =
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true); TEST_EQ(result, true);
TEST_EQ_STR(jsongen.c_str(), jsonfile.c_str()); TEST_EQ_STR(jsongen.c_str(), jsonfile.c_str());
@@ -588,8 +593,7 @@ void ParseAndGenerateTextTest() {
(test_data_path + "monster_test.fbs").c_str()); (test_data_path + "monster_test.fbs").c_str());
// Now we got this set up, we can parse by just specifying the identifier, // Now we got this set up, we can parse by just specifying the identifier,
// the correct schema will be loaded on the fly: // the correct schema will be loaded on the fly:
auto buf = registry.TextToFlatBuffer(jsonfile.c_str(), auto buf = registry.TextToFlatBuffer(jsonfile.c_str(), MonsterIdentifier());
MonsterIdentifier());
// If this fails, check registry.lasterror_. // If this fails, check registry.lasterror_.
TEST_NOTNULL(buf.data()); TEST_NOTNULL(buf.data());
// Test the buffer, to be sure: // Test the buffer, to be sure:
@@ -606,8 +610,8 @@ void ParseAndGenerateTextTest() {
void ReflectionTest(uint8_t *flatbuf, size_t length) { void ReflectionTest(uint8_t *flatbuf, size_t length) {
// Load a binary schema. // Load a binary schema.
std::string bfbsfile; std::string bfbsfile;
TEST_EQ(flatbuffers::LoadFile( TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_test.bfbs").c_str(),
(test_data_path + "monster_test.bfbs").c_str(), true, &bfbsfile), true, &bfbsfile),
true); true);
// Verify it, just in case: // Verify it, just in case:
@@ -661,16 +665,18 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
// Get struct field through reflection // Get struct field through reflection
auto pos_struct = flatbuffers::GetFieldStruct(root, *pos_field_ptr); auto pos_struct = flatbuffers::GetFieldStruct(root, *pos_field_ptr);
TEST_NOTNULL(pos_struct); TEST_NOTNULL(pos_struct);
TEST_EQ(flatbuffers::GetAnyFieldF( TEST_EQ(flatbuffers::GetAnyFieldF(*pos_struct,
*pos_struct, *pos_table_ptr->fields()->LookupByKey("z")), 3.0f); *pos_table_ptr->fields()->LookupByKey("z")),
3.0f);
auto test3_field = pos_table_ptr->fields()->LookupByKey("test3"); auto test3_field = pos_table_ptr->fields()->LookupByKey("test3");
auto test3_struct = flatbuffers::GetFieldStruct(*pos_struct, *test3_field); auto test3_struct = flatbuffers::GetFieldStruct(*pos_struct, *test3_field);
TEST_NOTNULL(test3_struct); TEST_NOTNULL(test3_struct);
auto test3_object = schema.objects()->Get(test3_field->type()->index()); auto test3_object = schema.objects()->Get(test3_field->type()->index());
TEST_EQ(flatbuffers::GetAnyFieldF( TEST_EQ(flatbuffers::GetAnyFieldF(*test3_struct,
*test3_struct, *test3_object->fields()->LookupByKey("a")), 10); *test3_object->fields()->LookupByKey("a")),
10);
// We can also modify it. // We can also modify it.
flatbuffers::SetField<uint16_t>(&root, hp_field, 200); flatbuffers::SetField<uint16_t>(&root, hp_field, 200);
@@ -703,8 +709,9 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
// Get the root. // Get the root.
// This time we wrap the result from GetAnyRoot in a smartpointer that // This time we wrap the result from GetAnyRoot in a smartpointer that
// will keep rroot valid as resizingbuf resizes. // will keep rroot valid as resizingbuf resizes.
auto rroot = flatbuffers::piv(flatbuffers::GetAnyRoot( auto rroot = flatbuffers::piv(
flatbuffers::vector_data(resizingbuf)), resizingbuf); flatbuffers::GetAnyRoot(flatbuffers::vector_data(resizingbuf)),
resizingbuf);
SetString(schema, "totally new string", GetFieldS(**rroot, name_field), SetString(schema, "totally new string", GetFieldS(**rroot, name_field),
&resizingbuf); &resizingbuf);
// Here resizingbuf has changed, but rroot is still valid. // Here resizingbuf has changed, but rroot is still valid.
@@ -712,8 +719,7 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
// Now lets extend a vector by 100 elements (10 -> 110). // Now lets extend a vector by 100 elements (10 -> 110).
auto &inventory_field = *fields->LookupByKey("inventory"); auto &inventory_field = *fields->LookupByKey("inventory");
auto rinventory = flatbuffers::piv( auto rinventory = flatbuffers::piv(
flatbuffers::GetFieldV<uint8_t>(**rroot, inventory_field), flatbuffers::GetFieldV<uint8_t>(**rroot, inventory_field), resizingbuf);
resizingbuf);
flatbuffers::ResizeVector<uint8_t>(schema, 110, 50, *rinventory, flatbuffers::ResizeVector<uint8_t>(schema, 110, 50, *rinventory,
&resizingbuf); &resizingbuf);
// rinventory still valid, so lets read from it. // rinventory still valid, so lets read from it.
@@ -741,24 +747,23 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
// Add the contents of it to our existing FlatBuffer. // Add the contents of it to our existing FlatBuffer.
// We do this last, so the pointer doesn't get invalidated (since it is // We do this last, so the pointer doesn't get invalidated (since it is
// at the end of the buffer): // at the end of the buffer):
auto string_ptr = flatbuffers::AddFlatBuffer(resizingbuf, auto string_ptr = flatbuffers::AddFlatBuffer(
stringfbb.GetBufferPointer(), resizingbuf, stringfbb.GetBufferPointer(), stringfbb.GetSize());
stringfbb.GetSize());
// Finally, set the new value in the vector. // Finally, set the new value in the vector.
rtestarrayofstring->MutateOffset(2, string_ptr); rtestarrayofstring->MutateOffset(2, string_ptr);
TEST_EQ_STR(rtestarrayofstring->Get(0)->c_str(), "bob"); TEST_EQ_STR(rtestarrayofstring->Get(0)->c_str(), "bob");
TEST_EQ_STR(rtestarrayofstring->Get(2)->c_str(), "hank"); TEST_EQ_STR(rtestarrayofstring->Get(2)->c_str(), "hank");
// Test integrity of all resize operations above. // Test integrity of all resize operations above.
flatbuffers::Verifier resize_verifier( flatbuffers::Verifier resize_verifier(
reinterpret_cast<const uint8_t *>( reinterpret_cast<const uint8_t *>(flatbuffers::vector_data(resizingbuf)),
flatbuffers::vector_data(resizingbuf)),
resizingbuf.size()); resizingbuf.size());
TEST_EQ(VerifyMonsterBuffer(resize_verifier), true); TEST_EQ(VerifyMonsterBuffer(resize_verifier), true);
// Test buffer is valid using reflection as well // Test buffer is valid using reflection as well
TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(), TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(),
flatbuffers::vector_data(resizingbuf), flatbuffers::vector_data(resizingbuf),
resizingbuf.size()), true); resizingbuf.size()),
true);
// As an additional test, also set it on the name field. // As an additional test, also set it on the name field.
// Note: unlike the name change above, this just overwrites the offset, // Note: unlike the name change above, this just overwrites the offset,
@@ -770,21 +775,22 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
// tables and other things out of other FlatBuffers into a FlatBufferBuilder, // tables and other things out of other FlatBuffers into a FlatBufferBuilder,
// either part or whole. // either part or whole.
flatbuffers::FlatBufferBuilder fbb; flatbuffers::FlatBufferBuilder fbb;
auto root_offset = flatbuffers::CopyTable(fbb, schema, *root_table, auto root_offset = flatbuffers::CopyTable(
*flatbuffers::GetAnyRoot(flatbuf), fbb, schema, *root_table, *flatbuffers::GetAnyRoot(flatbuf), true);
true);
fbb.Finish(root_offset, MonsterIdentifier()); fbb.Finish(root_offset, MonsterIdentifier());
// Test that it was copied correctly: // Test that it was copied correctly:
AccessFlatBufferTest(fbb.GetBufferPointer(), fbb.GetSize()); AccessFlatBufferTest(fbb.GetBufferPointer(), fbb.GetSize());
// Test buffer is valid using reflection as well // Test buffer is valid using reflection as well
TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(), TEST_EQ(flatbuffers::Verify(schema, *schema.root_table(),
fbb.GetBufferPointer(), fbb.GetSize()), true); fbb.GetBufferPointer(), fbb.GetSize()),
true);
} }
void MiniReflectFlatBuffersTest(uint8_t *flatbuf) { void MiniReflectFlatBuffersTest(uint8_t *flatbuf) {
auto s = flatbuffers::FlatBufferToString(flatbuf, MonsterTypeTable()); auto s = flatbuffers::FlatBufferToString(flatbuf, MonsterTypeTable());
TEST_EQ_STR(s.c_str(), TEST_EQ_STR(
s.c_str(),
"{ " "{ "
"pos: { x: 1.0, y: 2.0, z: 3.0, test1: 0.0, test2: Red, test3: " "pos: { x: 1.0, y: 2.0, z: 3.0, test1: 0.0, test2: Red, test3: "
"{ a: 10, b: 20 } }, " "{ a: 10, b: 20 } }, "
@@ -795,10 +801,12 @@ void MiniReflectFlatBuffersTest(uint8_t *flatbuf) {
"test: { name: \"Fred\" }, " "test: { name: \"Fred\" }, "
"test4: [ { a: 10, b: 20 }, { a: 30, b: 40 } ], " "test4: [ { a: 10, b: 20 }, { a: 30, b: 40 } ], "
"testarrayofstring: [ \"bob\", \"fred\", \"bob\", \"fred\" ], " "testarrayofstring: [ \"bob\", \"fred\", \"bob\", \"fred\" ], "
"testarrayoftables: [ { hp: 1000, name: \"Barney\" }, { name: \"Fred\" }, " "testarrayoftables: [ { hp: 1000, name: \"Barney\" }, { name: \"Fred\" "
"}, "
"{ name: \"Wilma\" } ], " "{ name: \"Wilma\" } ], "
// TODO(wvo): should really print this nested buffer correctly. // TODO(wvo): should really print this nested buffer correctly.
"testnestedflatbuffer: [ 20, 0, 0, 0, 77, 79, 78, 83, 12, 0, 12, 0, 0, 0, " "testnestedflatbuffer: [ 20, 0, 0, 0, 77, 79, 78, 83, 12, 0, 12, 0, 0, "
"0, "
"4, 0, 6, 0, 8, 0, 12, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 13, 0, 0, 0, 78, " "4, 0, 6, 0, 8, 0, 12, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 13, 0, 0, 0, 78, "
"101, 115, 116, 101, 100, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0 ], " "101, 115, 116, 101, 100, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0 ], "
"testarrayofstring2: [ \"jane\", \"mary\" ], " "testarrayofstring2: [ \"jane\", \"mary\" ], "
@@ -815,11 +823,13 @@ void ParseProtoTest() {
// load the .proto and the golden file from disk // load the .proto and the golden file from disk
std::string protofile; std::string protofile;
std::string goldenfile; std::string goldenfile;
TEST_EQ(flatbuffers::LoadFile( TEST_EQ(
(test_data_path + "prototest/test.proto").c_str(), false, &protofile), flatbuffers::LoadFile((test_data_path + "prototest/test.proto").c_str(),
false, &protofile),
true); true);
TEST_EQ(flatbuffers::LoadFile( TEST_EQ(
(test_data_path + "prototest/test.golden").c_str(), false, &goldenfile), flatbuffers::LoadFile((test_data_path + "prototest/test.golden").c_str(),
false, &goldenfile),
true); true);
flatbuffers::IDLOptions opts; flatbuffers::IDLOptions opts;
@@ -841,9 +851,9 @@ void ParseProtoTest() {
TEST_EQ_STR(fbs.c_str(), goldenfile.c_str()); TEST_EQ_STR(fbs.c_str(), goldenfile.c_str());
} }
template<typename T> void CompareTableFieldValue(flatbuffers::Table *table, template<typename T>
flatbuffers::voffset_t voffset, void CompareTableFieldValue(flatbuffers::Table *table,
T val) { flatbuffers::voffset_t voffset, T val) {
T read = table->GetField(voffset, static_cast<T>(0)); T read = table->GetField(voffset, static_cast<T>(0));
TEST_EQ(read, val); TEST_EQ(read, val);
} }
@@ -851,7 +861,6 @@ template<typename T> void CompareTableFieldValue(flatbuffers::Table *table,
// Low level stress/fuzz test: serialize/deserialize a variety of // Low level stress/fuzz test: serialize/deserialize a variety of
// different kinds of data in different combinations // different kinds of data in different combinations
void FuzzTest1() { void FuzzTest1() {
// Values we're testing against: chosen to ensure no bits get chopped // Values we're testing against: chosen to ensure no bits get chopped
// off anywhere, and also be different from eachother. // off anywhere, and also be different from eachother.
const uint8_t bool_val = true; const uint8_t bool_val = true;
@@ -951,8 +960,7 @@ void FuzzTest2() {
// Since we're generating schema and corresponding data in tandem, // Since we're generating schema and corresponding data in tandem,
// this convenience function adds strings to both at once. // this convenience function adds strings to both at once.
static void Add(RndDef (&definitions_l)[num_definitions], static void Add(RndDef (&definitions_l)[num_definitions],
std::string &schema_l, std::string &schema_l, const int instances_per_definition_l,
const int instances_per_definition_l,
const char *schema_add, const char *instance_add, const char *schema_add, const char *instance_add,
int definition) { int definition) {
schema_l += schema_add; schema_l += schema_add;
@@ -961,6 +969,7 @@ void FuzzTest2() {
} }
}; };
// clang-format off
#define AddToSchemaAndInstances(schema_add, instance_add) \ #define AddToSchemaAndInstances(schema_add, instance_add) \
RndDef::Add(definitions, schema, instances_per_definition, \ RndDef::Add(definitions, schema, instances_per_definition, \
schema_add, instance_add, definition) schema_add, instance_add, definition)
@@ -968,6 +977,7 @@ void FuzzTest2() {
#define Dummy() \ #define Dummy() \
RndDef::Add(definitions, schema, instances_per_definition, \ RndDef::Add(definitions, schema, instances_per_definition, \
"byte", "1", definition) "byte", "1", definition)
// clang-format on
RndDef definitions[num_definitions]; RndDef definitions[num_definitions];
@@ -994,9 +1004,8 @@ void FuzzTest2() {
// Deprecate 1 in deprecation_rate fields. Only table fields can be // Deprecate 1 in deprecation_rate fields. Only table fields can be
// deprecated. // deprecated.
// Don't deprecate the last field to avoid dangling commas in JSON. // Don't deprecate the last field to avoid dangling commas in JSON.
const bool deprecated = !is_struct && const bool deprecated =
!is_last_field && !is_struct && !is_last_field && (lcg_rand() % deprecation_rate == 0);
(lcg_rand() % deprecation_rate == 0);
std::string field_name = "f" + flatbuffers::NumToString(field); std::string field_name = "f" + flatbuffers::NumToString(field);
AddToSchemaAndInstances((" " + field_name + ":").c_str(), AddToSchemaAndInstances((" " + field_name + ":").c_str(),
@@ -1015,8 +1024,7 @@ void FuzzTest2() {
case flatbuffers::BASE_TYPE_VECTOR: case flatbuffers::BASE_TYPE_VECTOR:
if (is_struct) { if (is_struct) {
Dummy(); // No vectors in structs. Dummy(); // No vectors in structs.
} } else {
else {
AddToSchemaAndInstances("[ubyte]", AddToSchemaAndInstances("[ubyte]",
deprecated ? "" : "[\n0,\n1,\n255\n]"); deprecated ? "" : "[\n0,\n1,\n255\n]");
} }
@@ -1032,8 +1040,7 @@ void FuzzTest2() {
int instance = lcg_rand() % instances_per_definition; int instance = lcg_rand() % instances_per_definition;
AddToSchemaAndInstances( AddToSchemaAndInstances(
("D" + flatbuffers::NumToString(defref)).c_str(), ("D" + flatbuffers::NumToString(defref)).c_str(),
deprecated deprecated ? ""
? ""
: definitions[defref].instances[instance].c_str()); : definitions[defref].instances[instance].c_str());
} else { } else {
// If this is the first definition, we have no definition we can // If this is the first definition, we have no definition we can
@@ -1042,9 +1049,8 @@ void FuzzTest2() {
} }
break; break;
case flatbuffers::BASE_TYPE_BOOL: case flatbuffers::BASE_TYPE_BOOL:
AddToSchemaAndInstances("bool", deprecated AddToSchemaAndInstances(
? "" "bool", deprecated ? "" : (lcg_rand() % 2 ? "true" : "false"));
: (lcg_rand() % 2 ? "true" : "false"));
break; break;
default: default:
// All the scalar types. // All the scalar types.
@@ -1055,12 +1061,12 @@ void FuzzTest2() {
for (int inst = 0; inst < instances_per_definition; inst++) for (int inst = 0; inst < instances_per_definition; inst++)
definitions[definition].instances[inst] += definitions[definition].instances[inst] +=
flatbuffers::IsFloat(base_type) flatbuffers::IsFloat(base_type)
? flatbuffers::NumToString<double>(lcg_rand() % 128).c_str() ? flatbuffers::NumToString<double>(lcg_rand() % 128)
.c_str()
: flatbuffers::NumToString<int>(lcg_rand() % 128).c_str(); : flatbuffers::NumToString<int>(lcg_rand() % 128).c_str();
} }
} }
AddToSchemaAndInstances( AddToSchemaAndInstances(deprecated ? "(deprecated);\n" : ";\n",
deprecated ? "(deprecated);\n" : ";\n",
deprecated ? "" : is_last_field ? "\n" : ",\n"); deprecated ? "" : is_last_field ? "\n" : ",\n");
} }
AddToSchemaAndInstances("}\n\n", "}"); AddToSchemaAndInstances("}\n\n", "}");
@@ -1085,7 +1091,8 @@ void FuzzTest2() {
std::string jsongen; std::string jsongen;
parser.opts.indent_step = 0; parser.opts.indent_step = 0;
auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result =
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true); TEST_EQ(result, true);
if (jsongen != json) { if (jsongen != json) {
@@ -1105,11 +1112,13 @@ void FuzzTest2() {
TEST_NOTNULL(NULL); TEST_NOTNULL(NULL);
} }
// clang-format off
#ifdef FLATBUFFERS_TEST_VERBOSE #ifdef FLATBUFFERS_TEST_VERBOSE
TEST_OUTPUT_LINE("%dk schema tested with %dk of json\n", TEST_OUTPUT_LINE("%dk schema tested with %dk of json\n",
static_cast<int>(schema.length() / 1024), static_cast<int>(schema.length() / 1024),
static_cast<int>(json.length() / 1024)); static_cast<int>(json.length() / 1024));
#endif #endif
// clang-format on
} }
// Test that parser errors are actually generated. // Test that parser errors are actually generated.
@@ -1148,8 +1157,10 @@ void ErrorTest() {
TestError("table X { Y:int; } root_type X; { Y:", "string constant", true); TestError("table X { Y:int; } root_type X; { Y:", "string constant", true);
TestError("table X { Y:int; } root_type X; { \"Y\":1, }", "string constant", TestError("table X { Y:int; } root_type X; { \"Y\":1, }", "string constant",
true); true);
TestError("struct X { Y:int; Z:int; } table W { V:X; } root_type W; " TestError(
"{ V:{ Y:1 } }", "wrong number"); "struct X { Y:int; Z:int; } table W { V:X; } root_type W; "
"{ V:{ Y:1 } }",
"wrong number");
TestError("enum E:byte { A } table X { Y:E; } root_type X; { Y:U }", TestError("enum E:byte { A } table X { Y:E; } root_type X; { Y:U }",
"unknown enum value"); "unknown enum value");
TestError("table X { Y:byte; } root_type X; { Y:; }", "starting"); TestError("table X { Y:byte; } root_type X; { Y:; }", "starting");
@@ -1177,7 +1188,9 @@ template<typename T> T TestValue(const char *json, const char *type_name) {
// Simple schema. // Simple schema.
TEST_EQ(parser.Parse(std::string("table X { Y:" + std::string(type_name) + TEST_EQ(parser.Parse(std::string("table X { Y:" + std::string(type_name) +
"; } root_type X;").c_str()), true); "; } root_type X;")
.c_str()),
true);
TEST_EQ(parser.Parse(json), true); TEST_EQ(parser.Parse(json), true);
auto root = flatbuffers::GetRoot<flatbuffers::Table>( auto root = flatbuffers::GetRoot<flatbuffers::Table>(
@@ -1191,7 +1204,8 @@ bool FloatCompare(float a, float b) { return fabs(a - b) < 0.001; }
void ValueTest() { void ValueTest() {
// Test scientific notation numbers. // Test scientific notation numbers.
TEST_EQ(FloatCompare(TestValue<float>("{ Y:0.0314159e+2 }", "float"), TEST_EQ(FloatCompare(TestValue<float>("{ Y:0.0314159e+2 }", "float"),
(float)3.14159), true); (float)3.14159),
true);
// Test conversion functions. // Test conversion functions.
TEST_EQ(FloatCompare(TestValue<float>("{ Y:cos(rad(180)) }", "float"), -1), TEST_EQ(FloatCompare(TestValue<float>("{ Y:cos(rad(180)) }", "float"), -1),
@@ -1209,18 +1223,21 @@ void NestedListTest() {
flatbuffers::Parser parser1; flatbuffers::Parser parser1;
TEST_EQ(parser1.Parse("struct Test { a:short; b:byte; } table T { F:[Test]; }" TEST_EQ(parser1.Parse("struct Test { a:short; b:byte; } table T { F:[Test]; }"
"root_type T;" "root_type T;"
"{ F:[ [10,20], [30,40]] }"), true); "{ F:[ [10,20], [30,40]] }"),
true);
} }
void EnumStringsTest() { void EnumStringsTest() {
flatbuffers::Parser parser1; flatbuffers::Parser parser1;
TEST_EQ(parser1.Parse("enum E:byte { A, B, C } table T { F:[E]; }" TEST_EQ(parser1.Parse("enum E:byte { A, B, C } table T { F:[E]; }"
"root_type T;" "root_type T;"
"{ F:[ A, B, \"C\", \"A B C\" ] }"), true); "{ F:[ A, B, \"C\", \"A B C\" ] }"),
true);
flatbuffers::Parser parser2; flatbuffers::Parser parser2;
TEST_EQ(parser2.Parse("enum E:byte { A, B, C } table T { F:[int]; }" TEST_EQ(parser2.Parse("enum E:byte { A, B, C } table T { F:[int]; }"
"root_type T;" "root_type T;"
"{ F:[ \"E.C\", \"E.A E.B E.C\" ] }"), true); "{ F:[ \"E.C\", \"E.A E.B E.C\" ] }"),
true);
} }
void IntegerOutOfRangeTest() { void IntegerOutOfRangeTest() {
@@ -1263,24 +1280,29 @@ void IntegerBoundaryTest() {
TEST_EQ(TestValue<int32_t>("{ Y:-2147483648 }", "int"), (-2147483647 - 1)); TEST_EQ(TestValue<int32_t>("{ Y:-2147483648 }", "int"), (-2147483647 - 1));
TEST_EQ(TestValue<uint32_t>("{ Y:4294967295 }", "uint"), 4294967295); TEST_EQ(TestValue<uint32_t>("{ Y:4294967295 }", "uint"), 4294967295);
TEST_EQ(TestValue<uint32_t>("{ Y:0 }", "uint"), 0); TEST_EQ(TestValue<uint32_t>("{ Y:0 }", "uint"), 0);
TEST_EQ(TestValue<int64_t>("{ Y:9223372036854775807 }","long"), 9223372036854775807); TEST_EQ(TestValue<int64_t>("{ Y:9223372036854775807 }", "long"),
TEST_EQ(TestValue<int64_t>("{ Y:-9223372036854775808 }","long"), (-9223372036854775807 - 1)); 9223372036854775807);
TEST_EQ(TestValue<uint64_t>("{ Y:18446744073709551615 }","ulong"), 18446744073709551615U); TEST_EQ(TestValue<int64_t>("{ Y:-9223372036854775808 }", "long"),
(-9223372036854775807 - 1));
TEST_EQ(TestValue<uint64_t>("{ Y:18446744073709551615 }", "ulong"),
18446744073709551615U);
TEST_EQ(TestValue<uint64_t>("{ Y:0 }", "ulong"), 0); TEST_EQ(TestValue<uint64_t>("{ Y:0 }", "ulong"), 0);
} }
void UnicodeTest() { void UnicodeTest() {
flatbuffers::Parser parser; flatbuffers::Parser parser;
// Without setting allow_non_utf8 = true, we treat \x sequences as byte sequences // Without setting allow_non_utf8 = true, we treat \x sequences as byte
// which are then validated as UTF-8. // sequences which are then validated as UTF-8.
TEST_EQ(parser.Parse("table T { F:string; }" TEST_EQ(parser.Parse("table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC" "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
"\\u5225\\u30B5\\u30A4\\u30C8\\xE2\\x82\\xAC\\u0080\\uD83D\\uDE0E\" }"), "\\u5225\\u30B5\\u30A4\\u30C8\\xE2\\x82\\xAC\\u0080\\uD8"
"3D\\uDE0E\" }"),
true); true);
std::string jsongen; std::string jsongen;
parser.opts.indent_step = -1; parser.opts.indent_step = -1;
auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result =
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true); TEST_EQ(result, true);
TEST_EQ_STR(jsongen.c_str(), TEST_EQ_STR(jsongen.c_str(),
"{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC" "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
@@ -1290,44 +1312,53 @@ void UnicodeTest() {
void UnicodeTestAllowNonUTF8() { void UnicodeTestAllowNonUTF8() {
flatbuffers::Parser parser; flatbuffers::Parser parser;
parser.opts.allow_non_utf8 = true; parser.opts.allow_non_utf8 = true;
TEST_EQ(parser.Parse("table T { F:string; }" TEST_EQ(
parser.Parse(
"table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC" "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
"\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"), true); "\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"),
true);
std::string jsongen; std::string jsongen;
parser.opts.indent_step = -1; parser.opts.indent_step = -1;
auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result =
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true); TEST_EQ(result, true);
TEST_EQ_STR(jsongen.c_str(), TEST_EQ_STR(
jsongen.c_str(),
"{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC" "{F: \"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
"\\u5225\\u30B5\\u30A4\\u30C8\\u0001\\x80\\u0080\\uD83D\\uDE0E\"}"); "\\u5225\\u30B5\\u30A4\\u30C8\\u0001\\x80\\u0080\\uD83D\\uDE0E\"}");
} }
void UnicodeTestGenerateTextFailsOnNonUTF8() { void UnicodeTestGenerateTextFailsOnNonUTF8() {
flatbuffers::Parser parser; flatbuffers::Parser parser;
// Allow non-UTF-8 initially to model what happens when we load a binary flatbuffer from disk // Allow non-UTF-8 initially to model what happens when we load a binary
// which contains non-UTF-8 strings. // flatbuffer from disk which contains non-UTF-8 strings.
parser.opts.allow_non_utf8 = true; parser.opts.allow_non_utf8 = true;
TEST_EQ(parser.Parse("table T { F:string; }" TEST_EQ(
parser.Parse(
"table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC" "{ F:\"\\u20AC\\u00A2\\u30E6\\u30FC\\u30B6\\u30FC"
"\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"), true); "\\u5225\\u30B5\\u30A4\\u30C8\\x01\\x80\\u0080\\uD83D\\uDE0E\" }"),
true);
std::string jsongen; std::string jsongen;
parser.opts.indent_step = -1; parser.opts.indent_step = -1;
// Now, disallow non-UTF-8 (the default behavior) so GenerateText indicates failure. // Now, disallow non-UTF-8 (the default behavior) so GenerateText indicates
// failure.
parser.opts.allow_non_utf8 = false; parser.opts.allow_non_utf8 = false;
auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result =
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, false); TEST_EQ(result, false);
} }
void UnicodeSurrogatesTest() { void UnicodeSurrogatesTest() {
flatbuffers::Parser parser; flatbuffers::Parser parser;
TEST_EQ( TEST_EQ(parser.Parse("table T { F:string (id: 0); }"
parser.Parse(
"table T { F:string (id: 0); }"
"root_type T;" "root_type T;"
"{ F:\"\\uD83D\\uDCA9\"}"), true); "{ F:\"\\uD83D\\uDCA9\"}"),
true);
auto root = flatbuffers::GetRoot<flatbuffers::Table>( auto root = flatbuffers::GetRoot<flatbuffers::Table>(
parser.builder_.GetBufferPointer()); parser.builder_.GetBufferPointer());
auto string = root->GetPointer<flatbuffers::String *>( auto string = root->GetPointer<flatbuffers::String *>(
@@ -1339,23 +1370,28 @@ void UnicodeInvalidSurrogatesTest() {
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\\uD800\"}", "unpaired high surrogate"); "{ F:\"\\uD800\"}",
"unpaired high surrogate");
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\\uD800abcd\"}", "unpaired high surrogate"); "{ F:\"\\uD800abcd\"}",
"unpaired high surrogate");
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\\uD800\\n\"}", "unpaired high surrogate"); "{ F:\"\\uD800\\n\"}",
"unpaired high surrogate");
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\\uD800\\uD800\"}", "multiple high surrogates"); "{ F:\"\\uD800\\uD800\"}",
"multiple high surrogates");
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\\uDC00\"}", "unpaired low surrogate"); "{ F:\"\\uDC00\"}",
"unpaired low surrogate");
} }
void InvalidUTF8Test() { void InvalidUTF8Test() {
@@ -1363,89 +1399,107 @@ void InvalidUTF8Test() {
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\x80\"}", "illegal UTF-8 sequence"); "{ F:\"\x80\"}",
"illegal UTF-8 sequence");
// 2 byte pattern, string too short // 2 byte pattern, string too short
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xDF\"}", "illegal UTF-8 sequence"); "{ F:\"\xDF\"}",
"illegal UTF-8 sequence");
// 3 byte pattern, string too short // 3 byte pattern, string too short
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xEF\xBF\"}", "illegal UTF-8 sequence"); "{ F:\"\xEF\xBF\"}",
"illegal UTF-8 sequence");
// 4 byte pattern, string too short // 4 byte pattern, string too short
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xF7\xBF\xBF\"}", "illegal UTF-8 sequence"); "{ F:\"\xF7\xBF\xBF\"}",
"illegal UTF-8 sequence");
// "5 byte" pattern, string too short // "5 byte" pattern, string too short
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xFB\xBF\xBF\xBF\"}", "illegal UTF-8 sequence"); "{ F:\"\xFB\xBF\xBF\xBF\"}",
"illegal UTF-8 sequence");
// "6 byte" pattern, string too short // "6 byte" pattern, string too short
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xFD\xBF\xBF\xBF\xBF\"}", "illegal UTF-8 sequence"); "{ F:\"\xFD\xBF\xBF\xBF\xBF\"}",
"illegal UTF-8 sequence");
// "7 byte" pattern, string too short // "7 byte" pattern, string too short
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xFE\xBF\xBF\xBF\xBF\xBF\"}", "illegal UTF-8 sequence"); "{ F:\"\xFE\xBF\xBF\xBF\xBF\xBF\"}",
"illegal UTF-8 sequence");
// "5 byte" pattern, over max length of 4 bytes // "5 byte" pattern, over max length of 4 bytes
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xFB\xBF\xBF\xBF\xBF\"}", "illegal UTF-8 sequence"); "{ F:\"\xFB\xBF\xBF\xBF\xBF\"}",
"illegal UTF-8 sequence");
// "6 byte" pattern, over max length of 4 bytes // "6 byte" pattern, over max length of 4 bytes
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xFD\xBF\xBF\xBF\xBF\xBF\"}", "illegal UTF-8 sequence"); "{ F:\"\xFD\xBF\xBF\xBF\xBF\xBF\"}",
"illegal UTF-8 sequence");
// "7 byte" pattern, over max length of 4 bytes // "7 byte" pattern, over max length of 4 bytes
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xFE\xBF\xBF\xBF\xBF\xBF\xBF\"}", "illegal UTF-8 sequence"); "{ F:\"\xFE\xBF\xBF\xBF\xBF\xBF\xBF\"}",
"illegal UTF-8 sequence");
// Three invalid encodings for U+000A (\n, aka NEWLINE) // Three invalid encodings for U+000A (\n, aka NEWLINE)
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xC0\x8A\"}", "illegal UTF-8 sequence"); "{ F:\"\xC0\x8A\"}",
"illegal UTF-8 sequence");
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xE0\x80\x8A\"}", "illegal UTF-8 sequence"); "{ F:\"\xE0\x80\x8A\"}",
"illegal UTF-8 sequence");
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xF0\x80\x80\x8A\"}", "illegal UTF-8 sequence"); "{ F:\"\xF0\x80\x80\x8A\"}",
"illegal UTF-8 sequence");
// Two invalid encodings for U+00A9 (COPYRIGHT SYMBOL) // Two invalid encodings for U+00A9 (COPYRIGHT SYMBOL)
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xE0\x81\xA9\"}", "illegal UTF-8 sequence"); "{ F:\"\xE0\x81\xA9\"}",
"illegal UTF-8 sequence");
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xF0\x80\x81\xA9\"}", "illegal UTF-8 sequence"); "{ F:\"\xF0\x80\x81\xA9\"}",
"illegal UTF-8 sequence");
// Invalid encoding for U+20AC (EURO SYMBOL) // Invalid encoding for U+20AC (EURO SYMBOL)
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
"{ F:\"\xF0\x82\x82\xAC\"}", "illegal UTF-8 sequence"); "{ F:\"\xF0\x82\x82\xAC\"}",
"illegal UTF-8 sequence");
// UTF-16 surrogate values between U+D800 and U+DFFF cannot be encoded in UTF-8 // UTF-16 surrogate values between U+D800 and U+DFFF cannot be encoded in
// UTF-8
TestError( TestError(
"table T { F:string; }" "table T { F:string; }"
"root_type T;" "root_type T;"
// U+10400 "encoded" as U+D801 U+DC00 // U+10400 "encoded" as U+D801 U+DC00
"{ F:\"\xED\xA0\x81\xED\xB0\x80\"}", "illegal UTF-8 sequence"); "{ F:\"\xED\xA0\x81\xED\xB0\x80\"}",
"illegal UTF-8 sequence");
} }
void UnknownFieldsTest() { void UnknownFieldsTest() {
@@ -1463,11 +1517,13 @@ void UnknownFieldsTest() {
"unknown_array: [ 1, 2, 3, 4]," "unknown_array: [ 1, 2, 3, 4],"
"unknown_object: { i: 10 }," "unknown_object: { i: 10 },"
"\"unknown_object\": { \"i\": 10 }," "\"unknown_object\": { \"i\": 10 },"
"i:10}"), true); "i:10}"),
true);
std::string jsongen; std::string jsongen;
parser.opts.indent_step = -1; parser.opts.indent_step = -1;
auto result = GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen); auto result =
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
TEST_EQ(result, true); TEST_EQ(result, true);
TEST_EQ_STR(jsongen.c_str(), "{str: \"test\",i: 10}"); TEST_EQ_STR(jsongen.c_str(), "{str: \"test\",i: 10}");
} }
@@ -1479,12 +1535,14 @@ void ParseUnionTest() {
"union U { T }" "union U { T }"
"table V { X:U; }" "table V { X:U; }"
"root_type V;" "root_type V;"
"{ X:{ A:1 }, X_type: T }"), true); "{ X:{ A:1 }, X_type: T }"),
true);
// Unions must be parsable with prefixed namespace. // Unions must be parsable with prefixed namespace.
flatbuffers::Parser parser2; flatbuffers::Parser parser2;
TEST_EQ(parser2.Parse("namespace N; table A {} namespace; union U { N.A }" TEST_EQ(parser2.Parse("namespace N; table A {} namespace; union U { N.A }"
"table B { e:U; } root_type B;" "table B { e:U; } root_type B;"
"{ e_type: N_A, e: {} }"), true); "{ e_type: N_A, e: {} }"),
true);
} }
void UnionVectorTest() { void UnionVectorTest() {
@@ -1493,7 +1551,8 @@ void UnionVectorTest() {
std::string schemafile; std::string schemafile;
TEST_EQ(flatbuffers::LoadFile( TEST_EQ(flatbuffers::LoadFile(
(test_data_path + "union_vector/union_vector.fbs").c_str(), false, (test_data_path + "union_vector/union_vector.fbs").c_str(), false,
&schemafile), true); &schemafile),
true);
// parse schema. // parse schema.
flatbuffers::IDLOptions idl_opts; flatbuffers::IDLOptions idl_opts;
@@ -1521,11 +1580,9 @@ void UnionVectorTest() {
// create Movie. // create Movie.
const auto movie_offset = const auto movie_offset =
CreateMovie(fbb, CreateMovie(fbb, Character_Rapunzel,
Character_Rapunzel,
fbb.CreateStruct(Rapunzel(/*hair_length=*/6)).Union(), fbb.CreateStruct(Rapunzel(/*hair_length=*/6)).Union(),
fbb.CreateVector(types), fbb.CreateVector(types), fbb.CreateVector(characters));
fbb.CreateVector(characters));
FinishMovieBuffer(fbb, movie_offset); FinishMovieBuffer(fbb, movie_offset);
auto buf = fbb.GetBufferPointer(); auto buf = fbb.GetBufferPointer();
@@ -1581,9 +1638,10 @@ void UnionVectorTest() {
TestMovie(repacked_movie); TestMovie(repacked_movie);
auto s = flatbuffers::FlatBufferToString(fbb.GetBufferPointer(), auto s =
MovieTypeTable()); flatbuffers::FlatBufferToString(fbb.GetBufferPointer(), MovieTypeTable());
TEST_EQ_STR(s.c_str(), TEST_EQ_STR(
s.c_str(),
"{ main_character_type: Rapunzel, main_character: { hair_length: 6 }, " "{ main_character_type: Rapunzel, main_character: { hair_length: 6 }, "
"characters_type: [ Belle, MuLan, BookFan, Other, Unused ], " "characters_type: [ Belle, MuLan, BookFan, Other, Unused ], "
"characters: [ { books_read: 7 }, { sword_attack_damage: 5 }, " "characters: [ { books_read: 7 }, { sword_attack_damage: 5 }, "
@@ -1594,8 +1652,8 @@ void ConformTest() {
flatbuffers::Parser parser; flatbuffers::Parser parser;
TEST_EQ(parser.Parse("table T { A:int; } enum E:byte { A }"), true); TEST_EQ(parser.Parse("table T { A:int; } enum E:byte { A }"), true);
auto test_conform = [](flatbuffers::Parser &parser1, auto test_conform = [](flatbuffers::Parser &parser1, const char *test,
const char *test, const char *expected_err) { const char *expected_err) {
flatbuffers::Parser parser2; flatbuffers::Parser parser2;
TEST_EQ(parser2.Parse(test), true); TEST_EQ(parser2.Parse(test), true);
auto err = parser2.ConformTo(parser1); auto err = parser2.ConformTo(parser1);
@@ -1617,14 +1675,14 @@ void ParseProtoBufAsciiTest() {
// omits `,`, `:` before `{` and a couple of other features. // omits `,`, `:` before `{` and a couple of other features.
flatbuffers::Parser parser; flatbuffers::Parser parser;
parser.opts.protobuf_ascii_alike = true; parser.opts.protobuf_ascii_alike = true;
TEST_EQ(parser.Parse( TEST_EQ(
"table S { B:int; } table T { A:[int]; C:S; } root_type T;"), true); parser.Parse("table S { B:int; } table T { A:[int]; C:S; } root_type T;"),
true);
TEST_EQ(parser.Parse("{ A [1 2] C { B:2 }}"), true); TEST_EQ(parser.Parse("{ A [1 2] C { B:2 }}"), true);
// Similarly, in text output, it should omit these. // Similarly, in text output, it should omit these.
std::string text; std::string text;
auto ok = flatbuffers::GenerateText(parser, auto ok = flatbuffers::GenerateText(
parser.builder_.GetBufferPointer(), parser, parser.builder_.GetBufferPointer(), &text);
&text);
TEST_EQ(ok, true); TEST_EQ(ok, true);
TEST_EQ_STR(text.c_str(), TEST_EQ_STR(text.c_str(),
"{\n A [\n 1\n 2\n ]\n C {\n B: 2\n }\n}\n"); "{\n A [\n 1\n 2\n ]\n C {\n B: 2\n }\n}\n");
@@ -1635,7 +1693,9 @@ void FlexBuffersTest() {
flexbuffers::BUILDER_FLAG_SHARE_KEYS_AND_STRINGS); flexbuffers::BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
// Write the equivalent of: // Write the equivalent of:
// { vec: [ -100, "Fred", 4.0, false ], bar: [ 1, 2, 3 ], bar3: [ 1, 2, 3 ], foo: 100, bool: true, mymap: { foo: "Fred" } } // { vec: [ -100, "Fred", 4.0, false ], bar: [ 1, 2, 3 ], bar3: [ 1, 2, 3 ],
// foo: 100, bool: true, mymap: { foo: "Fred" } }
// clang-format off
#ifndef FLATBUFFERS_CPP98_STL #ifndef FLATBUFFERS_CPP98_STL
// It's possible to do this without std::function support as well. // It's possible to do this without std::function support as well.
slb.Map([&]() { slb.Map([&]() {
@@ -1687,6 +1747,7 @@ void FlexBuffersTest() {
printf("%d ", flatbuffers::vector_data(slb.GetBuffer())[i]); printf("%d ", flatbuffers::vector_data(slb.GetBuffer())[i]);
printf("\n"); printf("\n");
#endif #endif
// clang-format on
auto map = flexbuffers::GetRoot(slb.GetBuffer()).AsMap(); auto map = flexbuffers::GetRoot(slb.GetBuffer()).AsMap();
TEST_EQ(map.size(), 7); TEST_EQ(map.size(), 7);
@@ -1745,8 +1806,7 @@ void FlexBuffersTest() {
flatbuffers::Parser parser; flatbuffers::Parser parser;
slb.Clear(); slb.Clear();
auto jsontest = "{ a: [ 123, 456.0 ], b: \"hello\", c: true, d: false }"; auto jsontest = "{ a: [ 123, 456.0 ], b: \"hello\", c: true, d: false }";
TEST_EQ(parser.ParseFlexBuffer(jsontest, nullptr, &slb), TEST_EQ(parser.ParseFlexBuffer(jsontest, nullptr, &slb), true);
true);
auto jroot = flexbuffers::GetRoot(slb.GetBuffer()); auto jroot = flexbuffers::GetRoot(slb.GetBuffer());
auto jmap = jroot.AsMap(); auto jmap = jroot.AsMap();
auto jvec = jmap["a"].AsVector(); auto jvec = jmap["a"].AsVector();
@@ -1762,21 +1822,18 @@ void FlexBuffersTest() {
TEST_EQ_STR(jsontest, jsonback.c_str()); TEST_EQ_STR(jsontest, jsonback.c_str());
} }
void TypeAliasesTest() void TypeAliasesTest() {
{
flatbuffers::FlatBufferBuilder builder; flatbuffers::FlatBufferBuilder builder;
builder.Finish(CreateTypeAliases( builder.Finish(CreateTypeAliases(
builder, builder, flatbuffers::numeric_limits<int8_t>::min(),
flatbuffers::numeric_limits<int8_t>::min(),
flatbuffers::numeric_limits<uint8_t>::max(), flatbuffers::numeric_limits<uint8_t>::max(),
flatbuffers::numeric_limits<int16_t>::min(), flatbuffers::numeric_limits<int16_t>::min(),
flatbuffers::numeric_limits<uint16_t>::max(), flatbuffers::numeric_limits<uint16_t>::max(),
flatbuffers::numeric_limits<int32_t>::min(), flatbuffers::numeric_limits<int32_t>::min(),
flatbuffers::numeric_limits<uint32_t>::max(), flatbuffers::numeric_limits<uint32_t>::max(),
flatbuffers::numeric_limits<int64_t>::min(), flatbuffers::numeric_limits<int64_t>::min(),
flatbuffers::numeric_limits<uint64_t>::max(), flatbuffers::numeric_limits<uint64_t>::max(), 2.3f, 2.3));
2.3f, 2.3));
auto p = builder.GetBufferPointer(); auto p = builder.GetBufferPointer();
auto ta = flatbuffers::GetRoot<TypeAliases>(p); auto ta = flatbuffers::GetRoot<TypeAliases>(p);
@@ -1804,8 +1861,7 @@ void TypeAliasesTest()
} }
void EndianSwapTest() { void EndianSwapTest() {
TEST_EQ(flatbuffers::EndianSwap(static_cast<int16_t>(0x1234)), TEST_EQ(flatbuffers::EndianSwap(static_cast<int16_t>(0x1234)), 0x3412);
0x3412);
TEST_EQ(flatbuffers::EndianSwap(static_cast<int32_t>(0x12345678)), TEST_EQ(flatbuffers::EndianSwap(static_cast<int32_t>(0x12345678)),
0x78563412); 0x78563412);
TEST_EQ(flatbuffers::EndianSwap(static_cast<int64_t>(0x1234567890ABCDEF)), TEST_EQ(flatbuffers::EndianSwap(static_cast<int64_t>(0x1234567890ABCDEF)),
@@ -1814,6 +1870,7 @@ void EndianSwapTest() {
} }
int main(int /*argc*/, const char * /*argv*/ []) { int main(int /*argc*/, const char * /*argv*/ []) {
// clang-format off
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \ #if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
defined(_MSC_VER) && defined(_DEBUG) defined(_MSC_VER) && defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF
@@ -1856,6 +1913,7 @@ int main(int /*argc*/, const char * /*argv*/[]) {
ParseProtoTest(); ParseProtoTest();
UnionVectorTest(); UnionVectorTest();
#endif #endif
// clang-format on
FuzzTest1(); FuzzTest1();
FuzzTest2(); FuzzTest2();

View File

@@ -20,7 +20,7 @@ export class Attacker {
/** /**
* @type {flatbuffers.ByteBuffer} * @type {flatbuffers.ByteBuffer}
*/ */
bb: flatbuffers.ByteBuffer|null = null; bb: flatbuffers.ByteBuffer;
/** /**
* @type {number} * @type {number}
@@ -50,8 +50,8 @@ static getRootAsAttacker(bb:flatbuffers.ByteBuffer, obj?:Attacker):Attacker {
* @returns {number} * @returns {number}
*/ */
swordAttackDamage():number { swordAttackDamage():number {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; return offset ? this.bb.readInt32(this.bb_pos + offset) : 0;
}; };
/** /**
@@ -59,13 +59,13 @@ swordAttackDamage():number {
* @returns {boolean} * @returns {boolean}
*/ */
mutate_sword_attack_damage(value:number):boolean { mutate_sword_attack_damage(value:number):boolean {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
if (offset === 0) { if (offset === 0) {
return false; return false;
} }
this.bb!.writeInt32(this.bb_pos + offset, value); this.bb.writeInt32(this.bb_pos + offset, value);
return true; return true;
}; };
@@ -101,7 +101,7 @@ export class Rapunzel {
/** /**
* @type {flatbuffers.ByteBuffer} * @type {flatbuffers.ByteBuffer}
*/ */
bb: flatbuffers.ByteBuffer|null = null; bb: flatbuffers.ByteBuffer;
/** /**
* @type {number} * @type {number}
@@ -122,7 +122,7 @@ __init(i:number, bb:flatbuffers.ByteBuffer):Rapunzel {
* @returns {number} * @returns {number}
*/ */
hairLength():number { hairLength():number {
return this.bb!.readInt32(this.bb_pos); return this.bb.readInt32(this.bb_pos);
}; };
/** /**
@@ -130,13 +130,13 @@ hairLength():number {
* @returns {boolean} * @returns {boolean}
*/ */
mutate_hair_length(value:number):boolean { mutate_hair_length(value:number):boolean {
var offset = this.bb!.__offset(this.bb_pos, 0); var offset = this.bb.__offset(this.bb_pos, 0);
if (offset === 0) { if (offset === 0) {
return false; return false;
} }
this.bb!.writeInt32(this.bb_pos + offset, value); this.bb.writeInt32(this.bb_pos + offset, value);
return true; return true;
}; };
@@ -159,7 +159,7 @@ export class BookReader {
/** /**
* @type {flatbuffers.ByteBuffer} * @type {flatbuffers.ByteBuffer}
*/ */
bb: flatbuffers.ByteBuffer|null = null; bb: flatbuffers.ByteBuffer;
/** /**
* @type {number} * @type {number}
@@ -180,7 +180,7 @@ __init(i:number, bb:flatbuffers.ByteBuffer):BookReader {
* @returns {number} * @returns {number}
*/ */
booksRead():number { booksRead():number {
return this.bb!.readInt32(this.bb_pos); return this.bb.readInt32(this.bb_pos);
}; };
/** /**
@@ -188,13 +188,13 @@ booksRead():number {
* @returns {boolean} * @returns {boolean}
*/ */
mutate_books_read(value:number):boolean { mutate_books_read(value:number):boolean {
var offset = this.bb!.__offset(this.bb_pos, 0); var offset = this.bb.__offset(this.bb_pos, 0);
if (offset === 0) { if (offset === 0) {
return false; return false;
} }
this.bb!.writeInt32(this.bb_pos + offset, value); this.bb.writeInt32(this.bb_pos + offset, value);
return true; return true;
}; };
@@ -217,7 +217,7 @@ export class Movie {
/** /**
* @type {flatbuffers.ByteBuffer} * @type {flatbuffers.ByteBuffer}
*/ */
bb: flatbuffers.ByteBuffer|null = null; bb: flatbuffers.ByteBuffer;
/** /**
* @type {number} * @type {number}
@@ -255,8 +255,8 @@ static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean {
* @returns {Character} * @returns {Character}
*/ */
mainCharacterType():Character { mainCharacterType():Character {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
return offset ? /** @type {Character} */ (this.bb!.readUint8(this.bb_pos + offset)) : Character.NONE; return offset ? /** @type {Character} */ (this.bb.readUint8(this.bb_pos + offset)) : Character.NONE;
}; };
/** /**
@@ -264,13 +264,13 @@ mainCharacterType():Character {
* @returns {boolean} * @returns {boolean}
*/ */
mutate_main_character_type(value:Character):boolean { mutate_main_character_type(value:Character):boolean {
var offset = this.bb!.__offset(this.bb_pos, 4); var offset = this.bb.__offset(this.bb_pos, 4);
if (offset === 0) { if (offset === 0) {
return false; return false;
} }
this.bb!.writeUint8(this.bb_pos + offset, value); this.bb.writeUint8(this.bb_pos + offset, value);
return true; return true;
}; };
@@ -279,8 +279,8 @@ mutate_main_character_type(value:Character):boolean {
* @returns {?flatbuffers.Table} * @returns {?flatbuffers.Table}
*/ */
mainCharacter<T extends flatbuffers.Table>(obj:T):T|null { mainCharacter<T extends flatbuffers.Table>(obj:T):T|null {
var offset = this.bb!.__offset(this.bb_pos, 6); var offset = this.bb.__offset(this.bb_pos, 6);
return offset ? this.bb!.__union(obj, this.bb_pos + offset) : null; return offset ? this.bb.__union(obj, this.bb_pos + offset) : null;
}; };
/** /**
@@ -288,24 +288,24 @@ mainCharacter<T extends flatbuffers.Table>(obj:T):T|null {
* @returns {Character} * @returns {Character}
*/ */
charactersType(index: number):Character|null { charactersType(index: number):Character|null {
var offset = this.bb!.__offset(this.bb_pos, 8); var offset = this.bb.__offset(this.bb_pos, 8);
return offset ? /** @type {Character} */ (this.bb!.readUint8(this.bb!.__vector(this.bb_pos + offset) + index)) : /** @type {Character} */ (0); return offset ? /** @type {Character} */ (this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index)) : /** @type {Character} */ (0);
}; };
/** /**
* @returns {number} * @returns {number}
*/ */
charactersTypeLength():number { charactersTypeLength():number {
var offset = this.bb!.__offset(this.bb_pos, 8); var offset = this.bb.__offset(this.bb_pos, 8);
return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
}; };
/** /**
* @returns {Uint8Array} * @returns {Uint8Array}
*/ */
charactersTypeArray():Uint8Array|null { charactersTypeArray():Uint8Array|null {
var offset = this.bb!.__offset(this.bb_pos, 8); var offset = this.bb.__offset(this.bb_pos, 8);
return offset ? new Uint8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; return offset ? new Uint8Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null;
}; };
/** /**
@@ -314,16 +314,16 @@ charactersTypeArray():Uint8Array|null {
* @returns {?flatbuffers.Table} * @returns {?flatbuffers.Table}
*/ */
characters<T extends flatbuffers.Table>(index: number, obj:T):T|null { characters<T extends flatbuffers.Table>(index: number, obj:T):T|null {
var offset = this.bb!.__offset(this.bb_pos, 10); var offset = this.bb.__offset(this.bb_pos, 10);
return offset ? this.bb!.__union(obj, this.bb!.__vector(this.bb_pos + offset) + index * 4) : null; return offset ? this.bb.__union(obj, this.bb.__vector(this.bb_pos + offset) + index * 4) : null;
}; };
/** /**
* @returns {number} * @returns {number}
*/ */
charactersLength():number { charactersLength():number {
var offset = this.bb!.__offset(this.bb_pos, 10); var offset = this.bb.__offset(this.bb_pos, 10);
return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
}; };
/** /**