diff options
author | max42 <max42@yandex-team.com> | 2023-06-30 03:37:03 +0300 |
---|---|---|
committer | max42 <max42@yandex-team.com> | 2023-06-30 03:37:03 +0300 |
commit | fac2bd72b4b31ec3238292caf8fb2a8aaa6d6c4a (patch) | |
tree | b8cbc1deb00309c7f1a7ab6df520a76cf0b5c6d7 /contrib/libs/flatbuffers/include | |
parent | 7bf166b1a7ed0af927f230022b245af618e998c1 (diff) | |
download | ydb-fac2bd72b4b31ec3238292caf8fb2a8aaa6d6c4a.tar.gz |
YT-19324: move YT provider to ydb/library/yql
This commit is formed by the following script: https://paste.yandex-team.ru/6f92e4b8-efc5-4d34-948b-15ee2accd7e7/text.
This commit has zero effect on all projects that depend on YQL.
The summary of changes:
- `yql/providers/yt -> ydb/library/yql/providers/yt `- the whole implementation of YT provider is moved into YDB code base for further export as a part of YT YQL plugin shared library;
- `yql/providers/stat/{expr_nodes,uploader} -> ydb/library/yql/providers/stat/{expr_nodes,uploader}` - a small interface without implementation and the description of stat expr nodes;
- `yql/core/extract_predicate/ut -> ydb/library/yql/core/extract_predicate/ut`;
- `yql/core/{ut,ut_common} -> ydb/library/yql/core/{ut,ut_common}`;
- `yql/core` is gone;
- `yql/library/url_preprocessing -> ydb/library/yql/core/url_preprocessing`.
**NB**: all new targets inside `ydb/` are under `IF (NOT CMAKE_EXPORT)` clause which disables them from open-source cmake generation and ya make build. They will be enabled in the subsequent commits.
Diffstat (limited to 'contrib/libs/flatbuffers/include')
-rw-r--r-- | contrib/libs/flatbuffers/include/flatbuffers/code_generators.h | 235 | ||||
-rw-r--r-- | contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h | 640 | ||||
-rw-r--r-- | contrib/libs/flatbuffers/include/flatbuffers/flatc.h | 100 | ||||
-rw-r--r-- | contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h | 1636 | ||||
-rw-r--r-- | contrib/libs/flatbuffers/include/flatbuffers/hash.h | 127 | ||||
-rw-r--r-- | contrib/libs/flatbuffers/include/flatbuffers/idl.h | 1208 | ||||
-rw-r--r-- | contrib/libs/flatbuffers/include/flatbuffers/reflection.h | 502 | ||||
-rw-r--r-- | contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h | 1278 | ||||
-rw-r--r-- | contrib/libs/flatbuffers/include/flatbuffers/util.h | 698 |
9 files changed, 6424 insertions, 0 deletions
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h b/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h new file mode 100644 index 0000000000..09b773a468 --- /dev/null +++ b/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h @@ -0,0 +1,235 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_CODE_GENERATORS_H_ +#define FLATBUFFERS_CODE_GENERATORS_H_ + +#include <map> +#include <sstream> + +#include "idl.h" + +namespace flatbuffers { + +// Utility class to assist in generating code through use of text templates. +// +// Example code: +// CodeWriter code("\t"); +// code.SetValue("NAME", "Foo"); +// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }"; +// code.SetValue("NAME", "Bar"); +// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }"; +// std::cout << code.ToString() << std::endl; +// +// Output: +// void Foo() { printf("%s", "Foo"); } +// void Bar() { printf("%s", "Bar"); } +class CodeWriter { + public: + CodeWriter(std::string pad = std::string()) + : pad_(pad), cur_ident_lvl_(0), ignore_ident_(false) {} + + // Clears the current "written" code. + void Clear() { + stream_.str(""); + stream_.clear(); + } + + // Associates a key with a value. All subsequent calls to operator+=, where + // the specified key is contained in {{ and }} delimiters will be replaced by + // the given value. + void SetValue(const std::string &key, const std::string &value) { + value_map_[key] = value; + } + + std::string GetValue(const std::string &key) const { + const auto it = value_map_.find(key); + return it == value_map_.end() ? "" : it->second; + } + + // Appends the given text to the generated code as well as a newline + // character. Any text within {{ and }} delimiters is replaced by values + // previously stored in the CodeWriter by calling SetValue above. The newline + // will be suppressed if the text ends with the \\ character. + void operator+=(std::string text); + + // Returns the current contents of the CodeWriter as a std::string. + std::string ToString() const { return stream_.str(); } + + // Increase ident level for writing code + void IncrementIdentLevel() { cur_ident_lvl_++; } + // Decrease ident level for writing code + void DecrementIdentLevel() { + if (cur_ident_lvl_) cur_ident_lvl_--; + } + + void SetPadding(const std::string &padding) { pad_ = padding; } + + private: + std::map<std::string, std::string> value_map_; + std::stringstream stream_; + std::string pad_; + int cur_ident_lvl_; + bool ignore_ident_; + + // Add ident padding (tab or space) based on ident level + void AppendIdent(std::stringstream &stream); +}; + +class BaseGenerator { + public: + virtual bool generate() = 0; + + static std::string NamespaceDir(const Parser &parser, const std::string &path, + const Namespace &ns, + const bool dasherize = false); + + static std::string ToDasherizedCase(const std::string pascal_case); + + std::string GeneratedFileName(const std::string &path, + const std::string &file_name, + const IDLOptions &options) const; + + protected: + BaseGenerator(const Parser &parser, const std::string &path, + const std::string &file_name, std::string qualifying_start, + std::string qualifying_separator, std::string default_extension) + : parser_(parser), + path_(path), + file_name_(file_name), + qualifying_start_(qualifying_start), + qualifying_separator_(qualifying_separator), + default_extension_(default_extension) {} + virtual ~BaseGenerator() {} + + // No copy/assign. + BaseGenerator &operator=(const BaseGenerator &); + BaseGenerator(const BaseGenerator &); + + std::string NamespaceDir(const Namespace &ns, + const bool dasherize = false) const; + + static const char *FlatBuffersGeneratedWarning(); + + static std::string FullNamespace(const char *separator, const Namespace &ns); + + static std::string LastNamespacePart(const Namespace &ns); + + // tracks the current namespace for early exit in WrapInNameSpace + // c++, java and csharp returns a different namespace from + // the following default (no early exit, always fully qualify), + // which works for js and php + virtual const Namespace *CurrentNameSpace() const { return nullptr; } + + // Ensure that a type is prefixed with its namespace even within + // its own namespace to avoid conflict between generated method + // names and similarly named classes or structs + std::string WrapInNameSpace(const Namespace *ns, + const std::string &name) const; + + std::string WrapInNameSpace(const Definition &def) const; + + std::string GetNameSpace(const Definition &def) const; + + const Parser &parser_; + const std::string &path_; + const std::string &file_name_; + const std::string qualifying_start_; + const std::string qualifying_separator_; + const std::string default_extension_; +}; + +struct CommentConfig { + const char *first_line; + const char *content_line_prefix; + const char *last_line; +}; + +extern void GenComment(const std::vector<std::string> &dc, + std::string *code_ptr, const CommentConfig *config, + const char *prefix = ""); + +class FloatConstantGenerator { + public: + virtual ~FloatConstantGenerator() {} + std::string GenFloatConstant(const FieldDef &field) const; + + private: + virtual std::string Value(double v, const std::string &src) const = 0; + virtual std::string Inf(double v) const = 0; + virtual std::string NaN(double v) const = 0; + + virtual std::string Value(float v, const std::string &src) const = 0; + virtual std::string Inf(float v) const = 0; + virtual std::string NaN(float v) const = 0; + + template<typename T> + std::string GenFloatConstantImpl(const FieldDef &field) const; +}; + +class SimpleFloatConstantGenerator : public FloatConstantGenerator { + public: + SimpleFloatConstantGenerator(const char *nan_number, + const char *pos_inf_number, + const char *neg_inf_number); + + private: + std::string Value(double v, + const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Inf(double v) const FLATBUFFERS_OVERRIDE; + std::string NaN(double v) const FLATBUFFERS_OVERRIDE; + + std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Inf(float v) const FLATBUFFERS_OVERRIDE; + std::string NaN(float v) const FLATBUFFERS_OVERRIDE; + + const std::string nan_number_; + const std::string pos_inf_number_; + const std::string neg_inf_number_; +}; + +// C++, C#, Java like generator. +class TypedFloatConstantGenerator : public FloatConstantGenerator { + public: + TypedFloatConstantGenerator(const char *double_prefix, + const char *single_prefix, const char *nan_number, + const char *pos_inf_number, + const char *neg_inf_number = ""); + + private: + std::string Value(double v, + const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Inf(double v) const FLATBUFFERS_OVERRIDE; + + std::string NaN(double v) const FLATBUFFERS_OVERRIDE; + + std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; + std::string Inf(float v) const FLATBUFFERS_OVERRIDE; + std::string NaN(float v) const FLATBUFFERS_OVERRIDE; + + std::string MakeNaN(const std::string &prefix) const; + std::string MakeInf(bool neg, const std::string &prefix) const; + + const std::string double_prefix_; + const std::string single_prefix_; + const std::string nan_number_; + const std::string pos_inf_number_; + const std::string neg_inf_number_; +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_CODE_GENERATORS_H_ diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h new file mode 100644 index 0000000000..a770983dca --- /dev/null +++ b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h @@ -0,0 +1,640 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_ITER_H_ +#define FLATBUFFERS_ITER_H_ + +#include "flatbuffers.h" +#include <optional> + +/// @file +namespace yandex { +namespace maps { +namespace flatbuffers_iter { + +#define FLATBUFFERS_FILE_IDENTIFIER_LENGTH 4 + +using flatbuffers::uoffset_t; +using flatbuffers::soffset_t; +using flatbuffers::voffset_t; +using flatbuffers::EndianScalar; + +// Wrapper for uoffset_t to allow safe template specialization. +template<typename T> struct Offset { + uoffset_t o; + Offset() : o(0) {} + Offset(uoffset_t _o) : o(_o) {} + Offset<void> Union() const { return Offset<void>(o); } +}; + +template<typename Iter> +inline bool hasContiguous(const Iter& spot, uoffset_t length) +{ + return spot.hasContiguous(length); +} + +inline bool hasContiguous(const uint8_t* /* spot */, uoffset_t /* length */) +{ + return true; +} + +template <typename Iter> +inline const uint8_t* getRawPointer(const Iter& spot) +{ + return spot.rawPointer(); +} + +inline const uint8_t* getRawPointer(const uint8_t* spot) +{ + return spot; +} + +template<typename T, typename Iter> +typename std::enable_if<sizeof(T) == 1, T>::type extractValue(const Iter& spot) +{ + typename std::remove_cv<T>::type ret; + std::memcpy(&ret, getRawPointer(spot), 1); + return ret; +} + +template<typename T, typename Iter> +typename std::enable_if<sizeof(T) != 1, T>::type extractValue(const Iter& spot) +{ + if (hasContiguous(spot, sizeof(T))) { + typename std::remove_cv<T>::type ret; + std::memcpy(&ret, getRawPointer(spot), sizeof(T)); + return ret; + } + Iter itr = spot; + alignas(T) uint8_t buf[sizeof(T)]; + for (std::size_t i = 0; i < sizeof(T); ++i) { + buf[i] = *itr; + ++itr; + } + return *reinterpret_cast<T*>(buf); +} + +template<typename T, typename Iter> T ReadScalar(Iter p) { + return EndianScalar(extractValue<T>(p)); +} + +// When we read serialized data from memory, in the case of most scalars, +// we want to just read T, but in the case of Offset, we want to actually +// perform the indirection and return a pointer. +// The template specialization below does just that. +// It is wrapped in a struct since function templates can't overload on the +// return type like this. +// The typedef is for the convenience of callers of this function +// (avoiding the need for a trailing return decltype) +template<typename T> struct IndirectHelper { + typedef T return_type; + typedef T mutable_return_type; + static const size_t element_stride = sizeof(T); + template<typename Iter> + static return_type Read(const Iter& p, uoffset_t i) { + return i ? EndianScalar(extractValue<return_type>(p+sizeof(return_type)*i)) : EndianScalar(extractValue<return_type>(p)); + } +}; +template<typename T> struct IndirectHelper<Offset<T>> { + typedef std::optional<T> return_type; + typedef std::optional<T> mutable_return_type; + static const size_t element_stride = sizeof(uoffset_t); + template<typename Iter> + static return_type Read(Iter p, uoffset_t i) { + p += i * sizeof(uoffset_t); + return return_type(T(p + ReadScalar<uoffset_t>(p))); + } +}; +template<typename T> struct IndirectHelper<const T *> { +}; + + +// An STL compatible iterator implementation for Vector below, effectively +// calling Get() for every element. +template<typename T, typename IT, typename Iter> +struct VectorIterator + : public std::iterator<std::random_access_iterator_tag, IT, uoffset_t> { + + typedef std::iterator<std::random_access_iterator_tag, IT, uoffset_t> super_type; + +public: + VectorIterator(const Iter& data, uoffset_t i) : + data_(data + IndirectHelper<T>::element_stride * i) {} + VectorIterator(const VectorIterator &other) : data_(other.data_) {} + #ifndef FLATBUFFERS_CPP98_STL + VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {} + #endif + + VectorIterator &operator=(const VectorIterator &other) { + data_ = other.data_; + return *this; + } + + VectorIterator &operator=(VectorIterator &&other) { + data_ = other.data_; + return *this; + } + + bool operator==(const VectorIterator &other) const { + return data_ == other.data_; + } + + bool operator!=(const VectorIterator &other) const { + return data_ != other.data_; + } + + ptrdiff_t operator-(const VectorIterator &other) const { + return (data_ - other.data_) / IndirectHelper<T>::element_stride; + } + + typename super_type::value_type operator *() const { + return IndirectHelper<T>::Read(data_, 0); + } + + typename super_type::value_type operator->() const { + return IndirectHelper<T>::Read(data_, 0); + } + + VectorIterator &operator++() { + data_ += IndirectHelper<T>::element_stride; + return *this; + } + + VectorIterator operator++(int) { + VectorIterator temp(data_, 0); + data_ += IndirectHelper<T>::element_stride; + return temp; + } + + VectorIterator operator+(const uoffset_t &offset) { + return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, 0); + } + + VectorIterator& operator+=(const uoffset_t &offset) { + data_ += offset * IndirectHelper<T>::element_stride; + return *this; + } + + VectorIterator &operator--() { + data_ -= IndirectHelper<T>::element_stride; + return *this; + } + + VectorIterator operator--(int) { + VectorIterator temp(data_, 0); + data_ -= IndirectHelper<T>::element_stride; + return temp; + } + + VectorIterator operator-(const uoffset_t &offset) { + return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, 0); + } + + VectorIterator& operator-=(const uoffset_t &offset) { + data_ -= offset * IndirectHelper<T>::element_stride; + return *this; + } + +private: + Iter data_; +}; + +// This is used as a helper type for accessing vectors. +// Vector::data() assumes the vector elements start after the length field. +template<typename T, typename Iter> class Vector { +public: + typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type, Iter> + iterator; + typedef VectorIterator<T, typename IndirectHelper<T>::return_type, Iter> + const_iterator; + + Vector(Iter data): + data_(data) + {} + + uoffset_t size() const { return EndianScalar(extractValue<uoffset_t>(data_)); } + + // Deprecated: use size(). Here for backwards compatibility. + uoffset_t Length() const { return size(); } + + typedef typename IndirectHelper<T>::return_type return_type; + typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type; + + return_type Get(uoffset_t i) const { + assert(i < size()); + return IndirectHelper<T>::Read(Data(), i); + } + + return_type operator[](uoffset_t i) const { return Get(i); } + + // If this is a Vector of enums, T will be its storage type, not the enum + // type. This function makes it convenient to retrieve value with enum + // type E. + template<typename E> E GetEnum(uoffset_t i) const { + return static_cast<E>(Get(i)); + } + + const Iter GetStructFromOffset(size_t o) const { + return Data() + o; + } + + iterator begin() { return iterator(Data(), 0); } + const_iterator begin() const { return const_iterator(Data(), 0); } + + iterator end() { return iterator(Data(), size()); } + const_iterator end() const { return const_iterator(Data(), size()); } + + // The raw data in little endian format. Use with care. + const Iter Data() const { + return data_ + sizeof(uoffset_t); + } + + Iter Data() { + return data_ + sizeof(uoffset_t); + } + + template<typename K> return_type LookupByKey(K key) const { + auto search_result = std::lower_bound(begin(), end(), key, KeyCompare<K>); + + if (search_result == end() || (*search_result)->KeyCompareWithValue(key) != 0) { + return std::nullopt; // Key not found. + } + + return *search_result; + } + + operator Iter() const + { + return data_; + } + +protected: + Iter data_; + +private: + template<typename K> static int KeyCompare(const return_type& ap, const K& bp) { + return ap->KeyCompareWithValue(bp) < 0; + } +}; + +// Represent a vector much like the template above, but in this case we +// don't know what the element types are (used with reflection.h). +template <typename Iter> +class VectorOfAny { +public: + VectorOfAny(Iter data): + data_(data) + {} + + uoffset_t size() const { return EndianScalar(extractValue<uoffset_t>(data_)); } + + const Iter Data() const { + return data_; + } + Iter Data() { + return data_; + } +protected: + + Iter data_; +}; + +// Convenient helper function to get the length of any vector, regardless +// of wether it is null or not (the field is not set). +template<typename T, typename Iter> static inline size_t VectorLength(const std::optional<Vector<T, Iter>> &v) { + return v ? v->Length() : 0; +} + +template <typename Iter> struct String : public Vector<char, Iter> { + using Vector<char,Iter>::Vector; + using Vector<char,Iter>::data_; + + std::string str() const { + if (hasContiguous(data_, sizeof(uoffset_t) + this->Length())) + return std::string(reinterpret_cast<const char*>(getRawPointer(data_)) + sizeof(uoffset_t), this->Length()); + return std::string(this->begin(), this->begin() + this->Length()); } + + bool operator <(const String &o) const { + return str() < o.str(); + } +}; + +// Converts a Field ID to a virtual table offset. +inline voffset_t FieldIndexToOffset(voffset_t field_id) { + // Should correspond to what EndTable() below builds up. + const int fixed_fields = 2; // Vtable size and Object Size. + return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t)); +} + +/// @endcond + +/// @cond FLATBUFFERS_INTERNAL +template<typename T, typename Iter> std::optional<T> GetMutableRoot(Iter begin) { + flatbuffers::EndianCheck(); + return T(begin + EndianScalar(extractValue<uoffset_t>(begin))); +} + +template<typename T, typename Iter> std::optional<T> GetRoot(Iter begin) { + return GetMutableRoot<T, Iter>(begin); +} + +template<typename T, typename Iter> std::optional<T> GetSizePrefixedRoot(Iter buf) { + return GetRoot<T, Iter>(buf + sizeof(uoffset_t)); +} + +// Helper to see if the identifier in a buffer has the expected value. + +template <typename Iter> inline bool BufferHasIdentifier(const Iter& buf, const char *identifier) { + return std::equal( + identifier, + identifier + std::min(std::strlen(identifier) + 1, static_cast<std::size_t>(FLATBUFFERS_FILE_IDENTIFIER_LENGTH)), + buf + sizeof(uoffset_t)); +} + +// Helper class to verify the integrity of a FlatBuffer +template <typename Iter> +class Verifier FLATBUFFERS_FINAL_CLASS { + public: + Verifier(const Iter& buf, size_t buf_len, size_t _max_depth = 64, + size_t _max_tables = 1000000) + : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth), + num_tables_(0), max_tables_(_max_tables) + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + , upper_bound_(buf) + #endif + {} + + // Central location where any verification failures register. + bool Check(bool ok) const { + #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE + assert(ok); + #endif + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + if (!ok) + upper_bound_ = buf_; + #endif + return ok; + } + + // Verify any range within the buffer. + bool Verify(const Iter& elem, size_t elem_len) const { + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + auto upper_bound = elem + elem_len; + if (upper_bound_ < upper_bound) + upper_bound_ = upper_bound; + #endif + return Check(elem_len <= (size_t) (end_ - buf_) && + elem >= buf_ && + elem <= end_ - elem_len); + } + + // Verify a range indicated by sizeof(T). + template<typename T> bool Verify(const Iter& elem) const { + return Verify(elem, sizeof(T)); + } + + template<typename T> bool VerifyTable(const std::optional<T>& table) { + return !table || table->Verify(*this); + } + + template<typename T> bool Verify(const std::optional<Vector<T, Iter>>& vec) const { + Iter end; + return !vec || + VerifyVector(static_cast<Iter>(*vec), sizeof(T), + &end); + } + + template<typename T> bool Verify(const std::optional<Vector<const T, Iter>>& vec) const { + return Verify(*reinterpret_cast<const std::optional<Vector<T, Iter>> *>(&vec)); + } + + bool Verify(const std::optional<String<Iter>>& str) const { + Iter end; + return !str || + (VerifyVector(static_cast<Iter>(*str), 1, &end) && + Verify(end, 1) && // Must have terminator + Check(*end == '\0')); // Terminating byte must be 0. + } + + // Common code between vectors and strings. + bool VerifyVector(const Iter& vec, size_t elem_size, + Iter *end) const { + // Check we can read the size field. + if (!Verify<uoffset_t>(vec)) return false; + // Check the whole array. If this is a string, the byte past the array + // must be 0. + auto size = ReadScalar<uoffset_t>(vec); + auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size; + if (!Check(size < max_elems)) + return false; // Protect against byte_size overflowing. + auto byte_size = sizeof(size) + elem_size * size; + *end = vec + byte_size; + return Verify(vec, byte_size); + } + + // Special case for string contents, after the above has been called. + bool VerifyVectorOfStrings(const std::optional<Vector<Offset<String<Iter>>, Iter>>& vec) const { + if (vec) { + for (uoffset_t i = 0; i < vec->size(); i++) { + if (!Verify(vec->Get(i))) return false; + } + } + return true; + } + + // Special case for table contents, after the above has been called. + template<typename T> bool VerifyVectorOfTables(const std::optional<Vector<Offset<T>, Iter>>& vec) { + if (vec) { + for (uoffset_t i = 0; i < vec->size(); i++) { + if (!vec->Get(i)->Verify(*this)) return false; + } + } + return true; + } + + template<typename T> bool VerifyBufferFromStart(const char *identifier, + const Iter& start) { + if (identifier && + (static_cast<std::size_t>(end_ - start) < 2 * sizeof(flatbuffers_iter::uoffset_t) || + !BufferHasIdentifier(start, identifier))) { + return false; + } + + // Call T::Verify, which must be in the generated code for this type. + return Verify<uoffset_t>(start) && + T(start + ReadScalar<uoffset_t>(start)). + Verify(*this) + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + && GetComputedSize() + #endif + ; + } + + // Verify this whole buffer, starting with root type T. + template<typename T> bool VerifyBuffer(const char *identifier) { + return VerifyBufferFromStart<T>(identifier, buf_); + } + + template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) { + return Verify<uoffset_t>(buf_) && + ReadScalar<uoffset_t>(buf_) == end_ - buf_ - sizeof(uoffset_t) && + VerifyBufferFromStart<T>(identifier, buf_ + sizeof(uoffset_t)); + } + + // Called at the start of a table to increase counters measuring data + // structure depth and amount, and possibly bails out with false if + // limits set by the constructor have been hit. Needs to be balanced + // with EndTable(). + bool VerifyComplexity() { + depth_++; + num_tables_++; + return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_); + } + + // Called at the end of a table to pop the depth count. + bool EndTable() { + depth_--; + return true; + } + + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + // Returns the message size in bytes + size_t GetComputedSize() const { + uintptr_t size = upper_bound_ - buf_; + // Align the size to uoffset_t + size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1); + return (buf_ + size > end_) ? 0 : size; + } + #endif + + private: + const Iter buf_; + const Iter end_; + size_t depth_; + size_t max_depth_; + size_t num_tables_; + size_t max_tables_; +#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + mutable const Iter upper_bound_; +#endif +}; + +// "structs" are flat structures that do not have an offset table, thus +// always have all members present and do not support forwards/backwards +// compatible extensions. +template <typename Iter> +class Struct FLATBUFFERS_FINAL_CLASS { + public: + template<typename T> T GetField(uoffset_t o) const { + return ReadScalar<T>(data_ + o); + } + + template<typename T> T GetStruct(uoffset_t o) const { + return T(data_ + o); + } + + private: + Iter data_; +}; + +// "tables" use an offset table (possibly shared) that allows fields to be +// omitted and added at will, but uses an extra indirection to read. +template<typename Iter> +class Table { + public: + Table(Iter data): data_(data) {} + + const Iter GetVTable() const { + return data_ - ReadScalar<soffset_t>(data_); + } + + // This gets the field offset for any of the functions below it, or 0 + // if the field was not present. + voffset_t GetOptionalFieldOffset(voffset_t field) const { + // The vtable offset is always at the start. + auto vtable = GetVTable(); + // The first element is the size of the vtable (fields + type id + itself). + auto vtsize = ReadScalar<voffset_t>(vtable); + // If the field we're accessing is outside the vtable, we're reading older + // data, so it's the same as if the offset was 0 (not present). + return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0; + } + + template<typename T> T GetField(voffset_t field, T defaultval) const { + auto field_offset = GetOptionalFieldOffset(field); + return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval; + } + + template<typename P> std::optional<P> GetPointer(voffset_t field) { + auto field_offset = GetOptionalFieldOffset(field); + auto p = data_ + field_offset; + return field_offset ? std::optional<P>(P(p + ReadScalar<uoffset_t>(p))) : std::nullopt; + } + + template<typename P> std::optional<P> GetPointer(voffset_t field) const { + return const_cast<Table *>(this)->template GetPointer<P>(field); + } + + template<typename P> P GetStruct(voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + auto p = data_ + field_offset; + return extractValue<P>(p); + } + + bool CheckField(voffset_t field) const { + return GetOptionalFieldOffset(field) != 0; + } + + // Verify the vtable of this table. + // Call this once per table, followed by VerifyField once per field. + bool VerifyTableStart(Verifier<Iter> &verifier) const { + // Check the vtable offset. + if (!verifier.template Verify<soffset_t>(data_)) return false; + auto vtable = GetVTable(); + // Check the vtable size field, then check vtable fits in its entirety. + return verifier.VerifyComplexity() && + verifier.template Verify<voffset_t>(vtable) && + (ReadScalar<voffset_t>(vtable) & (sizeof(voffset_t) - 1)) == 0 && + verifier.Verify(vtable, ReadScalar<voffset_t>(vtable)); + } + + // Verify a particular field. + template<typename T> bool VerifyField(const Verifier<Iter> &verifier, + voffset_t field) const { + // Calling GetOptionalFieldOffset should be safe now thanks to + // VerifyTable(). + auto field_offset = GetOptionalFieldOffset(field); + // Check the actual field. + return !field_offset || verifier.template Verify<T>(data_ + field_offset); + } + + // VerifyField for required fields. + template<typename T> bool VerifyFieldRequired(const Verifier<Iter> &verifier, + voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + return verifier.Check(field_offset != 0) && + verifier.template Verify<T>(data_ + field_offset); + } + + private: + Iter data_; +}; +/// @endcond +} // namespace flatbuffers_iter +} // namespace maps +} // namespace yandex + +#endif // FLATBUFFERS_H_ diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatc.h b/contrib/libs/flatbuffers/include/flatbuffers/flatc.h new file mode 100644 index 0000000000..1466b3651d --- /dev/null +++ b/contrib/libs/flatbuffers/include/flatbuffers/flatc.h @@ -0,0 +1,100 @@ +/* + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_FLATC_H_ +#define FLATBUFFERS_FLATC_H_ + +#include <functional> +#include <limits> +#include <string> + +#include "flatbuffers.h" +#include "idl.h" +#include "util.h" + +namespace flatbuffers { + +extern void LogCompilerWarn(const std::string &warn); +extern void LogCompilerError(const std::string &err); + +class FlatCompiler { + public: + // Output generator for the various programming languages and formats we + // support. + struct Generator { + typedef bool (*GenerateFn)(const flatbuffers::Parser &parser, + const std::string &path, + const std::string &file_name); + typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser, + const std::string &path, + const std::string &file_name); + + GenerateFn generate; + const char *generator_opt_short; + const char *generator_opt_long; + const char *lang_name; + bool schema_only; + GenerateFn generateGRPC; + flatbuffers::IDLOptions::Language lang; + const char *generator_help; + MakeRuleFn make_rule; + }; + + typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn, + bool show_exe_name); + + typedef void (*ErrorFn)(const FlatCompiler *flatc, const std::string &err, + bool usage, bool show_exe_name); + + // Parameters required to initialize the FlatCompiler. + struct InitParams { + InitParams() + : generators(nullptr), + num_generators(0), + warn_fn(nullptr), + error_fn(nullptr) {} + + const Generator *generators; + size_t num_generators; + WarnFn warn_fn; + ErrorFn error_fn; + }; + + explicit FlatCompiler(const InitParams ¶ms) : params_(params) {} + + int Compile(int argc, const char **argv); + + std::string GetUsageString(const char *program_name) const; + + private: + void ParseFile(flatbuffers::Parser &parser, const std::string &filename, + const std::string &contents, + std::vector<const char *> &include_directories) const; + + void LoadBinarySchema(Parser &parser, const std::string &filename, + const std::string &contents); + + void Warn(const std::string &warn, bool show_exe_name = true) const; + + void Error(const std::string &err, bool usage = true, + bool show_exe_name = true) const; + + InitParams params_; +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_FLATC_H_ diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h b/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h new file mode 100644 index 0000000000..d855b67731 --- /dev/null +++ b/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h @@ -0,0 +1,1636 @@ +/* + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_FLEXBUFFERS_H_ +#define FLATBUFFERS_FLEXBUFFERS_H_ + +#include <map> +// Used to select STL variant. +#include "base.h" +// We use the basic binary writing functions from the regular FlatBuffers. +#include "util.h" + +#ifdef _MSC_VER +# include <intrin.h> +#endif + +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4127) // C4127: conditional expression is constant +#endif + +namespace flexbuffers { + +class Reference; +class Map; + +// These are used in the lower 2 bits of a type field to determine the size of +// the elements (and or size field) of the item pointed to (e.g. vector). +enum BitWidth { + BIT_WIDTH_8 = 0, + BIT_WIDTH_16 = 1, + BIT_WIDTH_32 = 2, + BIT_WIDTH_64 = 3, +}; + +// These are used as the upper 6 bits of a type field to indicate the actual +// type. +enum Type { + FBT_NULL = 0, + FBT_INT = 1, + FBT_UINT = 2, + FBT_FLOAT = 3, + // Types above stored inline, types below store an offset. + FBT_KEY = 4, + FBT_STRING = 5, + FBT_INDIRECT_INT = 6, + FBT_INDIRECT_UINT = 7, + FBT_INDIRECT_FLOAT = 8, + FBT_MAP = 9, + FBT_VECTOR = 10, // Untyped. + FBT_VECTOR_INT = 11, // Typed any size (stores no type table). + FBT_VECTOR_UINT = 12, + FBT_VECTOR_FLOAT = 13, + FBT_VECTOR_KEY = 14, + // DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead. + // Read test.cpp/FlexBuffersDeprecatedTest() for details on why. + FBT_VECTOR_STRING_DEPRECATED = 15, + FBT_VECTOR_INT2 = 16, // Typed tuple (no type table, no size field). + FBT_VECTOR_UINT2 = 17, + FBT_VECTOR_FLOAT2 = 18, + FBT_VECTOR_INT3 = 19, // Typed triple (no type table, no size field). + FBT_VECTOR_UINT3 = 20, + FBT_VECTOR_FLOAT3 = 21, + FBT_VECTOR_INT4 = 22, // Typed quad (no type table, no size field). + FBT_VECTOR_UINT4 = 23, + FBT_VECTOR_FLOAT4 = 24, + FBT_BLOB = 25, + FBT_BOOL = 26, + FBT_VECTOR_BOOL = + 36, // To Allow the same type of conversion of type to vector type +}; + +inline bool IsInline(Type t) { return t <= FBT_FLOAT || t == FBT_BOOL; } + +inline bool IsTypedVectorElementType(Type t) { + return (t >= FBT_INT && t <= FBT_STRING) || t == FBT_BOOL; +} + +inline bool IsTypedVector(Type t) { + return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) || + t == FBT_VECTOR_BOOL; +} + +inline bool IsFixedTypedVector(Type t) { + return t >= FBT_VECTOR_INT2 && t <= FBT_VECTOR_FLOAT4; +} + +inline Type ToTypedVector(Type t, size_t fixed_len = 0) { + FLATBUFFERS_ASSERT(IsTypedVectorElementType(t)); + switch (fixed_len) { + case 0: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT); + case 2: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT2); + case 3: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT3); + case 4: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT4); + default: FLATBUFFERS_ASSERT(0); return FBT_NULL; + } +} + +inline Type ToTypedVectorElementType(Type t) { + FLATBUFFERS_ASSERT(IsTypedVector(t)); + return static_cast<Type>(t - FBT_VECTOR_INT + FBT_INT); +} + +inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) { + FLATBUFFERS_ASSERT(IsFixedTypedVector(t)); + auto fixed_type = t - FBT_VECTOR_INT2; + *len = static_cast<uint8_t>(fixed_type / 3 + + 2); // 3 types each, starting from length 2. + return static_cast<Type>(fixed_type % 3 + FBT_INT); +} + +// TODO: implement proper support for 8/16bit floats, or decide not to +// support them. +typedef int16_t half; +typedef int8_t quarter; + +// TODO: can we do this without conditionals using intrinsics or inline asm +// on some platforms? Given branch prediction the method below should be +// decently quick, but it is the most frequently executed function. +// We could do an (unaligned) 64-bit read if we ifdef out the platforms for +// which that doesn't work (or where we'd read into un-owned memory). +template<typename R, typename T1, typename T2, typename T4, typename T8> +R ReadSizedScalar(const uint8_t *data, uint8_t byte_width) { + return byte_width < 4 + ? (byte_width < 2 + ? static_cast<R>(flatbuffers::ReadScalar<T1>(data)) + : static_cast<R>(flatbuffers::ReadScalar<T2>(data))) + : (byte_width < 8 + ? static_cast<R>(flatbuffers::ReadScalar<T4>(data)) + : static_cast<R>(flatbuffers::ReadScalar<T8>(data))); +} + +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, byte_width); +} + +inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) { + // This is the "hottest" function (all offset lookups use this), so worth + // optimizing if possible. + // 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 + // the conditionals in ReadSizedScalar. Can also use inline asm. + // clang-format off + #if defined(_MSC_VER) && ((defined(_M_X64) && !defined(_M_ARM64EC)) || defined _M_IX86) + uint64_t u = 0; + __movsb(reinterpret_cast<uint8_t *>(&u), + reinterpret_cast<const uint8_t *>(data), byte_width); + return flatbuffers::EndianScalar(u); + #else + return ReadSizedScalar<uint64_t, uint8_t, uint16_t, uint32_t, uint64_t>( + data, byte_width); + #endif + // clang-format on +} + +inline double ReadDouble(const uint8_t *data, uint8_t byte_width) { + return ReadSizedScalar<double, quarter, half, float, double>(data, + byte_width); +} + +inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) { + return offset - ReadUInt64(offset, byte_width); +} + +template<typename T> const uint8_t *Indirect(const uint8_t *offset) { + return offset - flatbuffers::ReadScalar<T>(offset); +} + +inline BitWidth WidthU(uint64_t u) { +#define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width) \ + { \ + if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \ + } + FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 8); + FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 16); + FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 32); +#undef FLATBUFFERS_GET_FIELD_BIT_WIDTH + return BIT_WIDTH_64; +} + +inline BitWidth WidthI(int64_t i) { + auto u = static_cast<uint64_t>(i) << 1; + return WidthU(i >= 0 ? u : ~u); +} + +inline BitWidth WidthF(double f) { + return static_cast<double>(static_cast<float>(f)) == f ? BIT_WIDTH_32 + : BIT_WIDTH_64; +} + +// Base class of all types below. +// Points into the data buffer and allows access to one type. +class Object { + public: + Object(const uint8_t *data, uint8_t byte_width) + : data_(data), byte_width_(byte_width) {} + + protected: + const uint8_t *data_; + uint8_t byte_width_; +}; + +// Object that has a size, obtained either from size prefix, or elsewhere. +class Sized : public Object { + public: + // Size prefix. + Sized(const uint8_t *data, uint8_t byte_width) + : Object(data, byte_width), size_(read_size()) {} + // Manual size. + Sized(const uint8_t *data, uint8_t byte_width, size_t sz) + : Object(data, byte_width), size_(sz) {} + size_t size() const { return size_; } + // Access size stored in `byte_width_` bytes before data_ pointer. + size_t read_size() const { + return static_cast<size_t>(ReadUInt64(data_ - byte_width_, byte_width_)); + } + + protected: + size_t size_; +}; + +class String : public Sized { + public: + // Size prefix. + String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {} + // Manual size. + String(const uint8_t *data, uint8_t byte_width, size_t sz) + : Sized(data, byte_width, sz) {} + + size_t length() const { return size(); } + const char *c_str() const { return reinterpret_cast<const char *>(data_); } + std::string str() const { return std::string(c_str(), size()); } + + static String EmptyString() { + static const char *empty_string = ""; + return String(reinterpret_cast<const uint8_t *>(empty_string), 1, 0); + } + bool IsTheEmptyString() const { return data_ == EmptyString().data_; } +}; + +class Blob : public Sized { + public: + Blob(const uint8_t *data_buf, uint8_t byte_width) + : Sized(data_buf, byte_width) {} + + static Blob EmptyBlob() { + static const uint8_t empty_blob[] = { 0 /*len*/ }; + return Blob(empty_blob + 1, 1); + } + bool IsTheEmptyBlob() const { return data_ == EmptyBlob().data_; } + const uint8_t *data() const { return data_; } +}; + +class Vector : public Sized { + public: + Vector(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {} + + Reference operator[](size_t i) const; + + static Vector EmptyVector() { + static const uint8_t empty_vector[] = { 0 /*len*/ }; + return Vector(empty_vector + 1, 1); + } + bool IsTheEmptyVector() const { return data_ == EmptyVector().data_; } +}; + +class TypedVector : public Sized { + public: + TypedVector(const uint8_t *data, uint8_t byte_width, Type element_type) + : Sized(data, byte_width), type_(element_type) {} + + Reference operator[](size_t i) const; + + static TypedVector EmptyTypedVector() { + static const uint8_t empty_typed_vector[] = { 0 /*len*/ }; + return TypedVector(empty_typed_vector + 1, 1, FBT_INT); + } + bool IsTheEmptyVector() const { + return data_ == TypedVector::EmptyTypedVector().data_; + } + + Type ElementType() { return type_; } + + friend Reference; + + private: + Type type_; + + friend Map; +}; + +class FixedTypedVector : public Object { + public: + FixedTypedVector(const uint8_t *data, uint8_t byte_width, Type element_type, + uint8_t len) + : Object(data, byte_width), type_(element_type), len_(len) {} + + Reference operator[](size_t i) const; + + static FixedTypedVector EmptyFixedTypedVector() { + static const uint8_t fixed_empty_vector[] = { 0 /* unused */ }; + return FixedTypedVector(fixed_empty_vector, 1, FBT_INT, 0); + } + bool IsTheEmptyFixedTypedVector() const { + return data_ == FixedTypedVector::EmptyFixedTypedVector().data_; + } + + Type ElementType() { return type_; } + uint8_t size() { return len_; } + + private: + Type type_; + uint8_t len_; +}; + +class Map : public Vector { + public: + Map(const uint8_t *data, uint8_t byte_width) : Vector(data, byte_width) {} + + Reference operator[](const char *key) const; + Reference operator[](const std::string &key) const; + + Vector Values() const { return Vector(data_, byte_width_); } + + TypedVector Keys() const { + const size_t num_prefixed_fields = 3; + auto keys_offset = data_ - byte_width_ * num_prefixed_fields; + return TypedVector(Indirect(keys_offset, byte_width_), + static_cast<uint8_t>( + ReadUInt64(keys_offset + byte_width_, byte_width_)), + FBT_KEY); + } + + static Map EmptyMap() { + static const uint8_t empty_map[] = { + 0 /*keys_len*/, 0 /*keys_offset*/, 1 /*keys_width*/, 0 /*len*/ + }; + return Map(empty_map + 4, 1); + } + + bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; } +}; + +template<typename T> +void AppendToString(std::string &s, T &&v, bool keys_quoted) { + s += "[ "; + for (size_t i = 0; i < v.size(); i++) { + if (i) s += ", "; + v[i].ToString(true, keys_quoted, s); + } + s += " ]"; +} + +class Reference { + public: + Reference() + : data_(nullptr), + parent_width_(0), + byte_width_(BIT_WIDTH_8), + type_(FBT_NULL) {} + + Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width, + Type type) + : data_(data), + parent_width_(parent_width), + byte_width_(byte_width), + type_(type) {} + + Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type) + : data_(data), parent_width_(parent_width) { + byte_width_ = 1U << static_cast<BitWidth>(packed_type & 3); + type_ = static_cast<Type>(packed_type >> 2); + } + + Type GetType() const { return type_; } + + bool IsNull() const { return type_ == FBT_NULL; } + bool IsBool() const { return type_ == FBT_BOOL; } + bool IsInt() const { return type_ == FBT_INT || type_ == FBT_INDIRECT_INT; } + bool IsUInt() const { + return type_ == FBT_UINT || type_ == FBT_INDIRECT_UINT; + } + bool IsIntOrUint() const { return IsInt() || IsUInt(); } + bool IsFloat() const { + return type_ == FBT_FLOAT || type_ == FBT_INDIRECT_FLOAT; + } + bool IsNumeric() const { return IsIntOrUint() || IsFloat(); } + bool IsString() const { return type_ == FBT_STRING; } + bool IsKey() const { return type_ == FBT_KEY; } + bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; } + bool IsUntypedVector() const { return type_ == FBT_VECTOR; } + bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); } + bool IsFixedTypedVector() const { + return flexbuffers::IsFixedTypedVector(type_); + } + bool IsAnyVector() const { + return (IsTypedVector() || IsFixedTypedVector() || IsVector()); + } + bool IsMap() const { return type_ == FBT_MAP; } + bool IsBlob() const { return type_ == FBT_BLOB; } + bool AsBool() const { + return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_) + : AsUInt64()) != 0; + } + + // Reads any type as a int64_t. Never fails, does most sensible conversion. + // Truncates floats, strings are attempted to be parsed for a number, + // vectors/maps return their size. Returns 0 if all else fails. + int64_t AsInt64() const { + if (type_ == FBT_INT) { + // A fast path for the common case. + return ReadInt64(data_, parent_width_); + } else + switch (type_) { + case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_); + case FBT_UINT: return ReadUInt64(data_, parent_width_); + case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_); + case FBT_FLOAT: + return static_cast<int64_t>(ReadDouble(data_, parent_width_)); + case FBT_INDIRECT_FLOAT: + return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_)); + case FBT_NULL: return 0; + case FBT_STRING: return flatbuffers::StringToInt(AsString().c_str()); + case FBT_VECTOR: return static_cast<int64_t>(AsVector().size()); + case FBT_BOOL: return ReadInt64(data_, parent_width_); + default: + // Convert other things to int. + return 0; + } + } + + // TODO: could specialize these to not use AsInt64() if that saves + // extension ops in generated code, and use a faster op than ReadInt64. + int32_t AsInt32() const { return static_cast<int32_t>(AsInt64()); } + int16_t AsInt16() const { return static_cast<int16_t>(AsInt64()); } + int8_t AsInt8() const { return static_cast<int8_t>(AsInt64()); } + + uint64_t AsUInt64() const { + if (type_ == FBT_UINT) { + // A fast path for the common case. + return ReadUInt64(data_, parent_width_); + } else + switch (type_) { + case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_); + case FBT_INT: return ReadInt64(data_, parent_width_); + case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_); + case FBT_FLOAT: + return static_cast<uint64_t>(ReadDouble(data_, parent_width_)); + case FBT_INDIRECT_FLOAT: + return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_)); + case FBT_NULL: return 0; + case FBT_STRING: return flatbuffers::StringToUInt(AsString().c_str()); + case FBT_VECTOR: return static_cast<uint64_t>(AsVector().size()); + case FBT_BOOL: return ReadUInt64(data_, parent_width_); + default: + // Convert other things to uint. + return 0; + } + } + + uint32_t AsUInt32() const { return static_cast<uint32_t>(AsUInt64()); } + uint16_t AsUInt16() const { return static_cast<uint16_t>(AsUInt64()); } + uint8_t AsUInt8() const { return static_cast<uint8_t>(AsUInt64()); } + + double AsDouble() const { + if (type_ == FBT_FLOAT) { + // A fast path for the common case. + return ReadDouble(data_, parent_width_); + } else + switch (type_) { + case FBT_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_); + case FBT_INT: + return static_cast<double>(ReadInt64(data_, parent_width_)); + case FBT_UINT: + return static_cast<double>(ReadUInt64(data_, parent_width_)); + case FBT_INDIRECT_INT: + return static_cast<double>(ReadInt64(Indirect(), byte_width_)); + case FBT_INDIRECT_UINT: + return static_cast<double>(ReadUInt64(Indirect(), byte_width_)); + case FBT_NULL: return 0.0; + case FBT_STRING: { + double d; + flatbuffers::StringToNumber(AsString().c_str(), &d); + return d; + } + case FBT_VECTOR: return static_cast<double>(AsVector().size()); + case FBT_BOOL: + return static_cast<double>(ReadUInt64(data_, parent_width_)); + default: + // Convert strings and other things to float. + return 0; + } + } + + float AsFloat() const { return static_cast<float>(AsDouble()); } + + const char *AsKey() const { + if (type_ == FBT_KEY || type_ == FBT_STRING) { + return reinterpret_cast<const char *>(Indirect()); + } else { + return ""; + } + } + + // This function returns the empty string if you try to read something that + // is not a string or key. + String AsString() const { + if (type_ == FBT_STRING) { + return String(Indirect(), byte_width_); + } else if (type_ == FBT_KEY) { + auto key = Indirect(); + return String(key, byte_width_, + strlen(reinterpret_cast<const char *>(key))); + } else { + return String::EmptyString(); + } + } + + // Unlike AsString(), this will convert any type to a std::string. + std::string ToString() const { + std::string s; + ToString(false, false, s); + return s; + } + + // Convert any type to a JSON-like string. strings_quoted determines if + // string values at the top level receive "" quotes (inside other values + // they always do). keys_quoted determines if keys are quoted, at any level. + // TODO(wvo): add further options to have indentation/newlines. + void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const { + if (type_ == FBT_STRING) { + String str(Indirect(), byte_width_); + if (strings_quoted) { + flatbuffers::EscapeString(str.c_str(), str.length(), &s, true, false); + } else { + s.append(str.c_str(), str.length()); + } + } else if (IsKey()) { + auto str = AsKey(); + if (keys_quoted) { + flatbuffers::EscapeString(str, strlen(str), &s, true, false); + } else { + s += str; + } + } else if (IsInt()) { + s += flatbuffers::NumToString(AsInt64()); + } else if (IsUInt()) { + s += flatbuffers::NumToString(AsUInt64()); + } else if (IsFloat()) { + s += flatbuffers::NumToString(AsDouble()); + } else if (IsNull()) { + s += "null"; + } else if (IsBool()) { + s += AsBool() ? "true" : "false"; + } else if (IsMap()) { + s += "{ "; + auto m = AsMap(); + auto keys = m.Keys(); + auto vals = m.Values(); + for (size_t i = 0; i < keys.size(); i++) { + keys[i].ToString(true, keys_quoted, s); + s += ": "; + vals[i].ToString(true, keys_quoted, s); + if (i < keys.size() - 1) s += ", "; + } + s += " }"; + } else if (IsVector()) { + AppendToString<Vector>(s, AsVector(), keys_quoted); + } else if (IsTypedVector()) { + AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted); + } else if (IsFixedTypedVector()) { + AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted); + } else if (IsBlob()) { + auto blob = AsBlob(); + flatbuffers::EscapeString(reinterpret_cast<const char *>(blob.data()), + blob.size(), &s, true, false); + } else { + s += "(?)"; + } + } + + // This function returns the empty blob if you try to read a not-blob. + // Strings can be viewed as blobs too. + Blob AsBlob() const { + if (type_ == FBT_BLOB || type_ == FBT_STRING) { + return Blob(Indirect(), byte_width_); + } else { + return Blob::EmptyBlob(); + } + } + + // This function returns the empty vector if you try to read a not-vector. + // Maps can be viewed as vectors too. + Vector AsVector() const { + if (type_ == FBT_VECTOR || type_ == FBT_MAP) { + return Vector(Indirect(), byte_width_); + } else { + return Vector::EmptyVector(); + } + } + + TypedVector AsTypedVector() const { + if (IsTypedVector()) { + auto tv = + TypedVector(Indirect(), byte_width_, ToTypedVectorElementType(type_)); + if (tv.type_ == FBT_STRING) { + // These can't be accessed as strings, since we don't know the bit-width + // of the size field, see the declaration of + // FBT_VECTOR_STRING_DEPRECATED above for details. + // We change the type here to be keys, which are a subtype of strings, + // and will ignore the size field. This will truncate strings with + // embedded nulls. + tv.type_ = FBT_KEY; + } + return tv; + } else { + return TypedVector::EmptyTypedVector(); + } + } + + FixedTypedVector AsFixedTypedVector() const { + if (IsFixedTypedVector()) { + uint8_t len = 0; + auto vtype = ToFixedTypedVectorElementType(type_, &len); + return FixedTypedVector(Indirect(), byte_width_, vtype, len); + } else { + return FixedTypedVector::EmptyFixedTypedVector(); + } + } + + Map AsMap() const { + if (type_ == FBT_MAP) { + return Map(Indirect(), byte_width_); + } else { + return Map::EmptyMap(); + } + } + + template<typename T> T As() const; + + // Experimental: Mutation functions. + // These allow scalars in an already created buffer to be updated in-place. + // Since by default scalars are stored in the smallest possible space, + // the new value may not fit, in which case these functions return false. + // To avoid this, you can construct the values you intend to mutate using + // Builder::ForceMinimumBitWidth. + bool MutateInt(int64_t i) { + if (type_ == FBT_INT) { + return Mutate(data_, i, parent_width_, WidthI(i)); + } else if (type_ == FBT_INDIRECT_INT) { + return Mutate(Indirect(), i, byte_width_, WidthI(i)); + } else if (type_ == FBT_UINT) { + auto u = static_cast<uint64_t>(i); + return Mutate(data_, u, parent_width_, WidthU(u)); + } else if (type_ == FBT_INDIRECT_UINT) { + auto u = static_cast<uint64_t>(i); + return Mutate(Indirect(), u, byte_width_, WidthU(u)); + } else { + return false; + } + } + + bool MutateBool(bool b) { + return type_ == FBT_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8); + } + + bool MutateUInt(uint64_t u) { + if (type_ == FBT_UINT) { + return Mutate(data_, u, parent_width_, WidthU(u)); + } else if (type_ == FBT_INDIRECT_UINT) { + return Mutate(Indirect(), u, byte_width_, WidthU(u)); + } else if (type_ == FBT_INT) { + auto i = static_cast<int64_t>(u); + return Mutate(data_, i, parent_width_, WidthI(i)); + } else if (type_ == FBT_INDIRECT_INT) { + auto i = static_cast<int64_t>(u); + return Mutate(Indirect(), i, byte_width_, WidthI(i)); + } else { + return false; + } + } + + bool MutateFloat(float f) { + if (type_ == FBT_FLOAT) { + return MutateF(data_, f, parent_width_, BIT_WIDTH_32); + } else if (type_ == FBT_INDIRECT_FLOAT) { + return MutateF(Indirect(), f, byte_width_, BIT_WIDTH_32); + } else { + return false; + } + } + + bool MutateFloat(double d) { + if (type_ == FBT_FLOAT) { + return MutateF(data_, d, parent_width_, WidthF(d)); + } else if (type_ == FBT_INDIRECT_FLOAT) { + return MutateF(Indirect(), d, byte_width_, WidthF(d)); + } else { + return false; + } + } + + bool MutateString(const char *str, size_t len) { + auto s = AsString(); + if (s.IsTheEmptyString()) return false; + // This is very strict, could allow shorter strings, but that creates + // garbage. + if (s.length() != len) return false; + memcpy(const_cast<char *>(s.c_str()), str, len); + return true; + } + bool MutateString(const char *str) { return MutateString(str, strlen(str)); } + bool MutateString(const std::string &str) { + return MutateString(str.data(), str.length()); + } + + private: + const uint8_t *Indirect() const { + return flexbuffers::Indirect(data_, parent_width_); + } + + template<typename T> + bool Mutate(const uint8_t *dest, T t, size_t byte_width, + BitWidth value_width) { + auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <= + byte_width; + if (fits) { + t = flatbuffers::EndianScalar(t); + memcpy(const_cast<uint8_t *>(dest), &t, byte_width); + } + return fits; + } + + template<typename T> + bool MutateF(const uint8_t *dest, T t, size_t byte_width, + BitWidth value_width) { + if (byte_width == sizeof(double)) + return Mutate(dest, static_cast<double>(t), byte_width, value_width); + if (byte_width == sizeof(float)) + return Mutate(dest, static_cast<float>(t), byte_width, value_width); + FLATBUFFERS_ASSERT(false); + return false; + } + + const uint8_t *data_; + uint8_t parent_width_; + uint8_t byte_width_; + Type type_; +}; + +// Template specialization for As(). +template<> inline bool Reference::As<bool>() const { return AsBool(); } + +template<> inline int8_t Reference::As<int8_t>() const { return AsInt8(); } +template<> inline int16_t Reference::As<int16_t>() const { return AsInt16(); } +template<> inline int32_t Reference::As<int32_t>() const { return AsInt32(); } +template<> inline int64_t Reference::As<int64_t>() const { return AsInt64(); } + +template<> inline uint8_t Reference::As<uint8_t>() const { return AsUInt8(); } +template<> inline uint16_t Reference::As<uint16_t>() const { + return AsUInt16(); +} +template<> inline uint32_t Reference::As<uint32_t>() const { + return AsUInt32(); +} +template<> inline uint64_t Reference::As<uint64_t>() const { + return AsUInt64(); +} + +template<> inline double Reference::As<double>() const { return AsDouble(); } +template<> inline float Reference::As<float>() const { return AsFloat(); } + +template<> inline String Reference::As<String>() const { return AsString(); } +template<> inline std::string Reference::As<std::string>() const { + return AsString().str(); +} + +template<> inline Blob Reference::As<Blob>() const { return AsBlob(); } +template<> inline Vector Reference::As<Vector>() const { return AsVector(); } +template<> inline TypedVector Reference::As<TypedVector>() const { + return AsTypedVector(); +} +template<> inline FixedTypedVector Reference::As<FixedTypedVector>() const { + return AsFixedTypedVector(); +} +template<> inline Map Reference::As<Map>() const { return AsMap(); } + +inline uint8_t PackedType(BitWidth bit_width, Type type) { + return static_cast<uint8_t>(bit_width | (type << 2)); +} + +inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, FBT_NULL); } + +// Vector accessors. +// Note: if you try to access outside of bounds, you get a Null value back +// instead. Normally this would be an assert, but since this is "dynamically +// typed" data, you may not want that (someone sends you a 2d vector and you +// wanted 3d). +// The Null converts seamlessly into a default value for any other type. +// TODO(wvo): Could introduce an #ifdef that makes this into an assert? +inline Reference Vector::operator[](size_t i) const { + auto len = size(); + if (i >= len) return Reference(nullptr, 1, NullPackedType()); + auto packed_type = (data_ + len * byte_width_)[i]; + auto elem = data_ + i * byte_width_; + return Reference(elem, byte_width_, packed_type); +} + +inline Reference TypedVector::operator[](size_t i) const { + auto len = size(); + if (i >= len) return Reference(nullptr, 1, NullPackedType()); + auto elem = data_ + i * byte_width_; + return Reference(elem, byte_width_, 1, type_); +} + +inline Reference FixedTypedVector::operator[](size_t i) const { + if (i >= len_) return Reference(nullptr, 1, NullPackedType()); + auto elem = data_ + i * byte_width_; + return Reference(elem, byte_width_, 1, type_); +} + +template<typename T> int KeyCompare(const void *key, const void *elem) { + auto str_elem = reinterpret_cast<const char *>( + Indirect<T>(reinterpret_cast<const uint8_t *>(elem))); + auto skey = reinterpret_cast<const char *>(key); + return strcmp(skey, str_elem); +} + +inline Reference Map::operator[](const char *key) const { + auto keys = Keys(); + // We can't pass keys.byte_width_ to the comparison function, so we have + // to pick the right one ahead of time. + int (*comp)(const void *, const void *) = nullptr; + switch (keys.byte_width_) { + case 1: comp = KeyCompare<uint8_t>; break; + case 2: comp = KeyCompare<uint16_t>; break; + case 4: comp = KeyCompare<uint32_t>; break; + case 8: comp = KeyCompare<uint64_t>; break; + } + auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp); + if (!res) return Reference(nullptr, 1, NullPackedType()); + auto i = (reinterpret_cast<uint8_t *>(res) - keys.data_) / keys.byte_width_; + return (*static_cast<const Vector *>(this))[i]; +} + +inline Reference Map::operator[](const std::string &key) const { + return (*this)[key.c_str()]; +} + +inline Reference GetRoot(const uint8_t *buffer, size_t size) { + // See Finish() below for the serialization counterpart of this. + // The root starts at the end of the buffer, so we parse backwards from there. + auto end = buffer + size; + auto byte_width = *--end; + auto packed_type = *--end; + end -= byte_width; // The root data item. + return Reference(end, byte_width, packed_type); +} + +inline Reference GetRoot(const std::vector<uint8_t> &buffer) { + return GetRoot(flatbuffers::vector_data(buffer), buffer.size()); +} + +// Flags that configure how the Builder behaves. +// The "Share" flags determine if the Builder automatically tries to pool +// this type. Pooling can reduce the size of serialized data if there are +// multiple maps of the same kind, at the expense of slightly slower +// serialization (the cost of lookups) and more memory use (std::set). +// By default this is on for keys, but off for strings. +// Turn keys off if you have e.g. only one map. +// Turn strings on if you expect many non-unique string values. +// Additionally, sharing key vectors can save space if you have maps with +// identical field populations. +enum BuilderFlag { + BUILDER_FLAG_NONE = 0, + BUILDER_FLAG_SHARE_KEYS = 1, + BUILDER_FLAG_SHARE_STRINGS = 2, + BUILDER_FLAG_SHARE_KEYS_AND_STRINGS = 3, + BUILDER_FLAG_SHARE_KEY_VECTORS = 4, + BUILDER_FLAG_SHARE_ALL = 7, +}; + +class Builder FLATBUFFERS_FINAL_CLASS { + public: + Builder(size_t initial_size = 256, + BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS) + : buf_(initial_size), + finished_(false), + has_duplicate_keys_(false), + flags_(flags), + force_min_bit_width_(BIT_WIDTH_8), + key_pool(KeyOffsetCompare(buf_)), + string_pool(StringOffsetCompare(buf_)) { + buf_.clear(); + } + +#ifdef FLATBUFFERS_DEFAULT_DECLARATION + Builder(Builder &&) = default; + Builder &operator=(Builder &&) = default; +#endif + + /// @brief Get the serialized buffer (after you call `Finish()`). + /// @return Returns a vector owned by this class. + const std::vector<uint8_t> &GetBuffer() const { + Finished(); + return buf_; + } + + // Size of the buffer. Does not include unfinished values. + size_t GetSize() const { return buf_.size(); } + + // Reset all state so we can re-use the buffer. + void Clear() { + buf_.clear(); + stack_.clear(); + finished_ = false; + // flags_ remains as-is; + force_min_bit_width_ = BIT_WIDTH_8; + key_pool.clear(); + string_pool.clear(); + } + + // All value constructing functions below have two versions: one that + // takes a key (for placement inside a map) and one that doesn't (for inside + // vectors and elsewhere). + + void Null() { stack_.push_back(Value()); } + void Null(const char *key) { + Key(key); + Null(); + } + + void Int(int64_t i) { stack_.push_back(Value(i, FBT_INT, WidthI(i))); } + void Int(const char *key, int64_t i) { + Key(key); + Int(i); + } + + void UInt(uint64_t u) { stack_.push_back(Value(u, FBT_UINT, WidthU(u))); } + void UInt(const char *key, uint64_t u) { + Key(key); + UInt(u); + } + + void Float(float f) { stack_.push_back(Value(f)); } + void Float(const char *key, float f) { + Key(key); + Float(f); + } + + void Double(double f) { stack_.push_back(Value(f)); } + void Double(const char *key, double d) { + Key(key); + Double(d); + } + + void Bool(bool b) { stack_.push_back(Value(b)); } + void Bool(const char *key, bool b) { + Key(key); + Bool(b); + } + + void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); } + void IndirectInt(const char *key, int64_t i) { + Key(key); + IndirectInt(i); + } + + void IndirectUInt(uint64_t u) { + PushIndirect(u, FBT_INDIRECT_UINT, WidthU(u)); + } + void IndirectUInt(const char *key, uint64_t u) { + Key(key); + IndirectUInt(u); + } + + void IndirectFloat(float f) { + PushIndirect(f, FBT_INDIRECT_FLOAT, BIT_WIDTH_32); + } + void IndirectFloat(const char *key, float f) { + Key(key); + IndirectFloat(f); + } + + void IndirectDouble(double f) { + PushIndirect(f, FBT_INDIRECT_FLOAT, WidthF(f)); + } + void IndirectDouble(const char *key, double d) { + Key(key); + IndirectDouble(d); + } + + size_t Key(const char *str, size_t len) { + auto sloc = buf_.size(); + WriteBytes(str, len + 1); + if (flags_ & BUILDER_FLAG_SHARE_KEYS) { + auto it = key_pool.find(sloc); + if (it != key_pool.end()) { + // Already in the buffer. Remove key we just serialized, and use + // existing offset instead. + buf_.resize(sloc); + sloc = *it; + } else { + key_pool.insert(sloc); + } + } + stack_.push_back(Value(static_cast<uint64_t>(sloc), FBT_KEY, BIT_WIDTH_8)); + return sloc; + } + + size_t Key(const char *str) { return Key(str, strlen(str)); } + size_t Key(const std::string &str) { return Key(str.c_str(), str.size()); } + + size_t String(const char *str, size_t len) { + auto reset_to = buf_.size(); + auto sloc = CreateBlob(str, len, 1, FBT_STRING); + if (flags_ & BUILDER_FLAG_SHARE_STRINGS) { + StringOffset so(sloc, len); + auto it = string_pool.find(so); + if (it != string_pool.end()) { + // Already in the buffer. Remove string we just serialized, and use + // existing offset instead. + buf_.resize(reset_to); + sloc = it->first; + stack_.back().u_ = sloc; + } else { + string_pool.insert(so); + } + } + return sloc; + } + size_t String(const char *str) { return String(str, strlen(str)); } + size_t String(const std::string &str) { + return String(str.c_str(), str.size()); + } + void String(const flexbuffers::String &str) { + String(str.c_str(), str.length()); + } + + void String(const char *key, const char *str) { + Key(key); + String(str); + } + void String(const char *key, const std::string &str) { + Key(key); + String(str); + } + void String(const char *key, const flexbuffers::String &str) { + Key(key); + String(str); + } + + size_t Blob(const void *data, size_t len) { + return CreateBlob(data, len, 0, FBT_BLOB); + } + size_t Blob(const std::vector<uint8_t> &v) { + return CreateBlob(flatbuffers::vector_data(v), v.size(), 0, FBT_BLOB); + } + + // TODO(wvo): support all the FlexBuffer types (like flexbuffers::String), + // e.g. Vector etc. Also in overloaded versions. + // Also some FlatBuffers types? + + size_t StartVector() { return stack_.size(); } + size_t StartVector(const char *key) { + Key(key); + return stack_.size(); + } + size_t StartMap() { 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 + // alignment. + size_t EndVector(size_t start, bool typed, bool fixed) { + auto vec = CreateVector(start, stack_.size() - start, 1, typed, fixed); + // Remove temp elements and return vector. + stack_.resize(start); + stack_.push_back(vec); + return static_cast<size_t>(vec.u_); + } + + size_t EndMap(size_t start) { + // We should have interleaved keys and values on the stack. + // Make sure it is an even number: + auto len = stack_.size() - start; + FLATBUFFERS_ASSERT(!(len & 1)); + len /= 2; + // Make sure keys are all strings: + for (auto key = start; key < stack_.size(); key += 2) { + FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY); + } + // Now sort values, so later we can do a binary search lookup. + // We want to sort 2 array elements at a time. + struct TwoValue { + Value key; + Value val; + }; + // TODO(wvo): strict aliasing? + // TODO(wvo): allow the caller to indicate the data is already sorted + // for maximum efficiency? With an assert to check sortedness to make sure + // we're not breaking binary search. + // Or, we can track if the map is sorted as keys are added which would be + // be quite cheap (cheaper than checking it here), so we can skip this + // step automatically when appliccable, and encourage people to write in + // sorted fashion. + // std::sort is typically already a lot faster on sorted data though. + auto dict = + reinterpret_cast<TwoValue *>(flatbuffers::vector_data(stack_) + start); + std::sort(dict, dict + len, + [&](const TwoValue &a, const TwoValue &b) -> bool { + auto as = reinterpret_cast<const char *>( + flatbuffers::vector_data(buf_) + a.key.u_); + auto bs = reinterpret_cast<const char *>( + flatbuffers::vector_data(buf_) + b.key.u_); + auto comp = strcmp(as, bs); + // We want to disallow duplicate keys, since this results in a + // map where values cannot be found. + // But we can't assert here (since we don't want to fail on + // random JSON input) or have an error mechanism. + // Instead, we set has_duplicate_keys_ in the builder to + // signal this. + // TODO: Have to check for pointer equality, as some sort + // implementation apparently call this function with the same + // element?? Why? + if (!comp && &a != &b) has_duplicate_keys_ = true; + return comp < 0; + }); + // First create a vector out of all keys. + // TODO(wvo): if kBuilderFlagShareKeyVectors is true, see if we can share + // the first vector. + auto keys = CreateVector(start, len, 2, true, false); + auto vec = CreateVector(start + 1, len, 2, false, false, &keys); + // Remove temp elements and return map. + stack_.resize(start); + stack_.push_back(vec); + return static_cast<size_t>(vec.u_); + } + + // Call this after EndMap to see if the map had any duplicate keys. + // Any map with such keys won't be able to retrieve all values. + bool HasDuplicateKeys() const { return has_duplicate_keys_; } + + template<typename F> size_t Vector(F f) { + auto start = StartVector(); + f(); + return EndVector(start, false, false); + } + template<typename F, typename T> size_t Vector(F f, T &state) { + auto start = StartVector(); + f(state); + return EndVector(start, false, false); + } + template<typename F> size_t Vector(const char *key, F f) { + auto start = StartVector(key); + f(); + return EndVector(start, false, false); + } + template<typename F, typename T> + size_t Vector(const char *key, F f, T &state) { + auto start = StartVector(key); + f(state); + return EndVector(start, false, false); + } + + template<typename T> void Vector(const T *elems, size_t len) { + if (flatbuffers::is_scalar<T>::value) { + // This path should be a lot quicker and use less space. + ScalarVector(elems, len, false); + } else { + auto start = StartVector(); + for (size_t i = 0; i < len; i++) Add(elems[i]); + EndVector(start, false, false); + } + } + template<typename T> + void Vector(const char *key, const T *elems, size_t len) { + Key(key); + Vector(elems, len); + } + template<typename T> void Vector(const std::vector<T> &vec) { + Vector(flatbuffers::vector_data(vec), vec.size()); + } + + template<typename F> size_t TypedVector(F f) { + auto start = StartVector(); + f(); + return EndVector(start, true, false); + } + template<typename F, typename T> size_t TypedVector(F f, T &state) { + auto start = StartVector(); + f(state); + return EndVector(start, true, false); + } + template<typename F> size_t TypedVector(const char *key, F f) { + auto start = StartVector(key); + f(); + return EndVector(start, true, false); + } + template<typename F, typename T> + size_t TypedVector(const char *key, F f, T &state) { + auto start = StartVector(key); + f(state); + return EndVector(start, true, false); + } + + template<typename T> size_t FixedTypedVector(const T *elems, size_t len) { + // We only support a few fixed vector lengths. Anything bigger use a + // regular typed vector. + FLATBUFFERS_ASSERT(len >= 2 && len <= 4); + // And only scalar values. + static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types"); + return ScalarVector(elems, len, true); + } + + template<typename T> + size_t FixedTypedVector(const char *key, const T *elems, size_t len) { + Key(key); + return FixedTypedVector(elems, len); + } + + template<typename F> size_t Map(F f) { + auto start = StartMap(); + f(); + return EndMap(start); + } + template<typename F, typename T> size_t Map(F f, T &state) { + auto start = StartMap(); + f(state); + return EndMap(start); + } + template<typename F> size_t Map(const char *key, F f) { + auto start = StartMap(key); + f(); + return EndMap(start); + } + template<typename F, typename T> size_t Map(const char *key, F f, T &state) { + auto start = StartMap(key); + f(state); + return EndMap(start); + } + template<typename T> void Map(const std::map<std::string, T> &map) { + auto start = StartMap(); + for (auto it = map.begin(); it != map.end(); ++it) + Add(it->first.c_str(), it->second); + EndMap(start); + } + + // If you wish to share a value explicitly (a value not shared automatically + // through one of the BUILDER_FLAG_SHARE_* flags) you can do so with these + // functions. Or if you wish to turn those flags off for performance reasons + // and still do some explicit sharing. For example: + // builder.IndirectDouble(M_PI); + // auto id = builder.LastValue(); // Remember where we stored it. + // .. more code goes here .. + // builder.ReuseValue(id); // Refers to same double by offset. + // LastValue works regardless of whether the value has a key or not. + // Works on any data type. + struct Value; + Value LastValue() { return stack_.back(); } + void ReuseValue(Value v) { stack_.push_back(v); } + void ReuseValue(const char *key, Value v) { + Key(key); + ReuseValue(v); + } + + // Overloaded Add that tries to call the correct function above. + void Add(int8_t i) { Int(i); } + void Add(int16_t i) { Int(i); } + void Add(int32_t i) { Int(i); } + void Add(int64_t i) { Int(i); } + void Add(uint8_t u) { UInt(u); } + void Add(uint16_t u) { UInt(u); } + void Add(uint32_t u) { UInt(u); } + void Add(uint64_t u) { UInt(u); } + void Add(float f) { Float(f); } + void Add(double d) { Double(d); } + void Add(bool b) { Bool(b); } + void Add(const char *str) { String(str); } + void Add(const std::string &str) { String(str); } + void Add(const flexbuffers::String &str) { String(str); } + + template<typename T> void Add(const std::vector<T> &vec) { Vector(vec); } + + template<typename T> void Add(const char *key, const T &t) { + Key(key); + Add(t); + } + + template<typename T> void Add(const std::map<std::string, T> &map) { + Map(map); + } + + template<typename T> void operator+=(const T &t) { Add(t); } + + // 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 + // they can later be updated without failing. + // Call with no arguments to reset. + void ForceMinimumBitWidth(BitWidth bw = BIT_WIDTH_8) { + force_min_bit_width_ = bw; + } + + void Finish() { + // If you hit this assert, you likely have objects that were never included + // in a parent. You need to have exactly one root to finish a buffer. + // Check your Start/End calls are matched, and all objects are inside + // some other object. + FLATBUFFERS_ASSERT(stack_.size() == 1); + + // Write root value. + auto byte_width = Align(stack_[0].ElemWidth(buf_.size(), 0)); + WriteAny(stack_[0], byte_width); + // Write root type. + Write(stack_[0].StoredPackedType(), 1); + // Write root size. Normally determined by parent, but root has no parent :) + Write(byte_width, 1); + + finished_ = true; + } + + private: + void Finished() const { + // If you get this assert, you're attempting to get access a buffer + // which hasn't been finished yet. Be sure to call + // Builder::Finish with your root object. + FLATBUFFERS_ASSERT(finished_); + } + + // Align to prepare for writing a scalar with a certain size. + uint8_t Align(BitWidth alignment) { + auto byte_width = 1U << alignment; + buf_.insert(buf_.end(), flatbuffers::PaddingBytes(buf_.size(), byte_width), + 0); + return static_cast<uint8_t>(byte_width); + } + + void WriteBytes(const void *val, size_t size) { + buf_.insert(buf_.end(), reinterpret_cast<const uint8_t *>(val), + reinterpret_cast<const uint8_t *>(val) + size); + } + + template<typename T> void Write(T val, size_t byte_width) { + FLATBUFFERS_ASSERT(sizeof(T) >= byte_width); + val = flatbuffers::EndianScalar(val); + WriteBytes(&val, byte_width); + } + + void WriteDouble(double f, uint8_t byte_width) { + switch (byte_width) { + case 8: Write(f, byte_width); break; + case 4: Write(static_cast<float>(f), byte_width); break; + // case 2: Write(static_cast<half>(f), byte_width); break; + // case 1: Write(static_cast<quarter>(f), byte_width); break; + default: FLATBUFFERS_ASSERT(0); + } + } + + void WriteOffset(uint64_t o, uint8_t byte_width) { + auto reloff = buf_.size() - o; + FLATBUFFERS_ASSERT(byte_width == 8 || reloff < 1ULL << (byte_width * 8)); + Write(reloff, byte_width); + } + + template<typename T> void PushIndirect(T val, Type type, BitWidth bit_width) { + auto byte_width = Align(bit_width); + auto iloc = buf_.size(); + Write(val, byte_width); + stack_.push_back(Value(static_cast<uint64_t>(iloc), type, bit_width)); + } + + static BitWidth WidthB(size_t byte_width) { + switch (byte_width) { + case 1: return BIT_WIDTH_8; + case 2: return BIT_WIDTH_16; + case 4: return BIT_WIDTH_32; + case 8: return BIT_WIDTH_64; + default: FLATBUFFERS_ASSERT(false); return BIT_WIDTH_64; + } + } + + template<typename T> static Type GetScalarType() { + static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types"); + return flatbuffers::is_floating_point<T>::value + ? FBT_FLOAT + : flatbuffers::is_same<T, bool>::value + ? FBT_BOOL + : (flatbuffers::is_unsigned<T>::value ? FBT_UINT + : FBT_INT); + } + + public: + // This was really intended to be private, except for LastValue/ReuseValue. + struct Value { + union { + int64_t i_; + uint64_t u_; + double f_; + }; + + Type type_; + + // For scalars: of itself, for vector: of its elements, for string: length. + BitWidth min_bit_width_; + + Value() : i_(0), type_(FBT_NULL), min_bit_width_(BIT_WIDTH_8) {} + + Value(bool b) + : u_(static_cast<uint64_t>(b)), + type_(FBT_BOOL), + min_bit_width_(BIT_WIDTH_8) {} + + Value(int64_t i, Type t, BitWidth bw) + : i_(i), type_(t), min_bit_width_(bw) {} + Value(uint64_t u, Type t, BitWidth bw) + : u_(u), type_(t), min_bit_width_(bw) {} + + Value(float f) + : f_(static_cast<double>(f)), + type_(FBT_FLOAT), + min_bit_width_(BIT_WIDTH_32) {} + Value(double f) : f_(f), type_(FBT_FLOAT), min_bit_width_(WidthF(f)) {} + + uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const { + return PackedType(StoredWidth(parent_bit_width_), type_); + } + + BitWidth ElemWidth(size_t buf_size, size_t elem_index) const { + if (IsInline(type_)) { + return min_bit_width_; + } else { + // We have an absolute offset, but want to store a relative offset + // elem_index elements beyond the current buffer end. Since whether + // the relative offset fits in a certain byte_width depends on + // the size of the elements before it (and their alignment), we have + // to test for each size in turn. + for (size_t byte_width = 1; + byte_width <= sizeof(flatbuffers::largest_scalar_t); + byte_width *= 2) { + // Where are we going to write this offset? + auto offset_loc = buf_size + + flatbuffers::PaddingBytes(buf_size, byte_width) + + elem_index * byte_width; + // Compute relative offset. + auto offset = offset_loc - u_; + // Does it fit? + auto bit_width = WidthU(offset); + if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) == + byte_width) + return bit_width; + } + FLATBUFFERS_ASSERT(false); // Must match one of the sizes above. + return BIT_WIDTH_64; + } + } + + BitWidth StoredWidth(BitWidth parent_bit_width_ = BIT_WIDTH_8) const { + if (IsInline(type_)) { + return (std::max)(min_bit_width_, parent_bit_width_); + } else { + return min_bit_width_; + } + } + }; + + private: + void WriteAny(const Value &val, uint8_t byte_width) { + switch (val.type_) { + case FBT_NULL: + case FBT_INT: Write(val.i_, byte_width); break; + case FBT_BOOL: + case FBT_UINT: Write(val.u_, byte_width); break; + case FBT_FLOAT: WriteDouble(val.f_, byte_width); break; + default: WriteOffset(val.u_, byte_width); break; + } + } + + size_t CreateBlob(const void *data, size_t len, size_t trailing, Type type) { + auto bit_width = WidthU(len); + auto byte_width = Align(bit_width); + Write<uint64_t>(len, byte_width); + auto sloc = buf_.size(); + WriteBytes(data, len + trailing); + stack_.push_back(Value(static_cast<uint64_t>(sloc), type, bit_width)); + return sloc; + } + + template<typename T> + size_t ScalarVector(const T *elems, size_t len, bool fixed) { + auto vector_type = GetScalarType<T>(); + auto byte_width = sizeof(T); + auto bit_width = WidthB(byte_width); + // If you get this assert, you're trying to write a vector with a size + // field that is bigger than the scalars you're trying to write (e.g. a + // byte vector > 255 elements). For such types, write a "blob" instead. + // TODO: instead of asserting, could write vector with larger elements + // instead, though that would be wasteful. + FLATBUFFERS_ASSERT(WidthU(len) <= bit_width); + Align(bit_width); + if (!fixed) Write<uint64_t>(len, byte_width); + auto vloc = buf_.size(); + for (size_t i = 0; i < len; i++) Write(elems[i], byte_width); + stack_.push_back(Value(static_cast<uint64_t>(vloc), + ToTypedVector(vector_type, fixed ? len : 0), + bit_width)); + return vloc; + } + + Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed, + bool fixed, const Value *keys = nullptr) { + FLATBUFFERS_ASSERT( + !fixed || + typed); // typed=false, fixed=true combination is not supported. + // Figure out smallest bit width we can store this vector with. + auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len)); + auto prefix_elems = 1; + if (keys) { + // If this vector is part of a map, we will pre-fix an offset to the keys + // to this vector. + bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0)); + prefix_elems += 2; + } + Type vector_type = FBT_KEY; + // Check bit widths and types for all elements. + for (size_t i = start; i < stack_.size(); i += step) { + auto elem_width = + stack_[i].ElemWidth(buf_.size(), i - start + prefix_elems); + bit_width = (std::max)(bit_width, elem_width); + if (typed) { + if (i == start) { + vector_type = stack_[i].type_; + } else { + // If you get this assert, you are writing a typed vector with + // elements that are not all the same type. + FLATBUFFERS_ASSERT(vector_type == stack_[i].type_); + } + } + } + // If you get this assert, your fixed types are not one of: + // Int / UInt / Float / Key. + FLATBUFFERS_ASSERT(!fixed || IsTypedVectorElementType(vector_type)); + auto byte_width = Align(bit_width); + // Write vector. First the keys width/offset if available, and size. + if (keys) { + WriteOffset(keys->u_, byte_width); + Write<uint64_t>(1ULL << keys->min_bit_width_, byte_width); + } + if (!fixed) Write<uint64_t>(vec_len, byte_width); + // Then the actual data. + auto vloc = buf_.size(); + for (size_t i = start; i < stack_.size(); i += step) { + WriteAny(stack_[i], byte_width); + } + // Then the types. + if (!typed) { + for (size_t i = start; i < stack_.size(); i += step) { + buf_.push_back(stack_[i].StoredPackedType(bit_width)); + } + } + return Value(static_cast<uint64_t>(vloc), + keys ? FBT_MAP + : (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0) + : FBT_VECTOR), + bit_width); + } + + // You shouldn't really be copying instances of this class. + Builder(const Builder &); + Builder &operator=(const Builder &); + + std::vector<uint8_t> buf_; + std::vector<Value> stack_; + + bool finished_; + bool has_duplicate_keys_; + + BuilderFlag flags_; + + BitWidth force_min_bit_width_; + + struct KeyOffsetCompare { + explicit KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {} + bool operator()(size_t a, size_t b) const { + auto stra = + reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a); + auto strb = + reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + b); + return strcmp(stra, strb) < 0; + } + const std::vector<uint8_t> *buf_; + }; + + typedef std::pair<size_t, size_t> StringOffset; + struct StringOffsetCompare { + explicit StringOffsetCompare(const std::vector<uint8_t> &buf) + : buf_(&buf) {} + bool operator()(const StringOffset &a, const StringOffset &b) const { + auto stra = reinterpret_cast<const char *>( + flatbuffers::vector_data(*buf_) + a.first); + auto strb = reinterpret_cast<const char *>( + flatbuffers::vector_data(*buf_) + b.first); + return strncmp(stra, strb, (std::min)(a.second, b.second) + 1) < 0; + } + const std::vector<uint8_t> *buf_; + }; + + typedef std::set<size_t, KeyOffsetCompare> KeyOffsetMap; + typedef std::set<StringOffset, StringOffsetCompare> StringOffsetMap; + + KeyOffsetMap key_pool; + StringOffsetMap string_pool; +}; + +} // namespace flexbuffers + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif // FLATBUFFERS_FLEXBUFFERS_H_ diff --git a/contrib/libs/flatbuffers/include/flatbuffers/hash.h b/contrib/libs/flatbuffers/include/flatbuffers/hash.h new file mode 100644 index 0000000000..52cc628cdf --- /dev/null +++ b/contrib/libs/flatbuffers/include/flatbuffers/hash.h @@ -0,0 +1,127 @@ +/* + * Copyright 2015 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_HASH_H_ +#define FLATBUFFERS_HASH_H_ + +#include <cstdint> +#include <cstring> + +#include "flatbuffers.h" + +namespace flatbuffers { + +template<typename T> struct FnvTraits { + static const T kFnvPrime; + static const T kOffsetBasis; +}; + +template<> struct FnvTraits<uint32_t> { + static const uint32_t kFnvPrime = 0x01000193; + static const uint32_t kOffsetBasis = 0x811C9DC5; +}; + +template<> struct FnvTraits<uint64_t> { + static const uint64_t kFnvPrime = 0x00000100000001b3ULL; + static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL; +}; + +template<typename T> T HashFnv1(const char *input) { + T hash = FnvTraits<T>::kOffsetBasis; + for (const char *c = input; *c; ++c) { + hash *= FnvTraits<T>::kFnvPrime; + hash ^= static_cast<unsigned char>(*c); + } + return hash; +} + +template<typename T> T HashFnv1a(const char *input) { + T hash = FnvTraits<T>::kOffsetBasis; + for (const char *c = input; *c; ++c) { + hash ^= static_cast<unsigned char>(*c); + hash *= FnvTraits<T>::kFnvPrime; + } + return hash; +} + +template<> inline uint16_t HashFnv1<uint16_t>(const char *input) { + uint32_t hash = HashFnv1<uint32_t>(input); + return (hash >> 16) ^ (hash & 0xffff); +} + +template<> inline uint16_t HashFnv1a<uint16_t>(const char *input) { + uint32_t hash = HashFnv1a<uint32_t>(input); + return (hash >> 16) ^ (hash & 0xffff); +} + +template<typename T> struct NamedHashFunction { + const char *name; + + typedef T (*HashFunction)(const char *); + HashFunction function; +}; + +const NamedHashFunction<uint16_t> kHashFunctions16[] = { + { "fnv1_16", HashFnv1<uint16_t> }, + { "fnv1a_16", HashFnv1a<uint16_t> }, +}; + +const NamedHashFunction<uint32_t> kHashFunctions32[] = { + { "fnv1_32", HashFnv1<uint32_t> }, + { "fnv1a_32", HashFnv1a<uint32_t> }, +}; + +const NamedHashFunction<uint64_t> kHashFunctions64[] = { + { "fnv1_64", HashFnv1<uint64_t> }, + { "fnv1a_64", HashFnv1a<uint64_t> }, +}; + +inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16( + const char *name) { + std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]); + for (std::size_t i = 0; i < size; ++i) { + if (std::strcmp(name, kHashFunctions16[i].name) == 0) { + return kHashFunctions16[i].function; + } + } + return nullptr; +} + +inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32( + const char *name) { + std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]); + for (std::size_t i = 0; i < size; ++i) { + if (std::strcmp(name, kHashFunctions32[i].name) == 0) { + return kHashFunctions32[i].function; + } + } + return nullptr; +} + +inline NamedHashFunction<uint64_t>::HashFunction FindHashFunction64( + const char *name) { + std::size_t size = sizeof(kHashFunctions64) / sizeof(kHashFunctions64[0]); + for (std::size_t i = 0; i < size; ++i) { + if (std::strcmp(name, kHashFunctions64[i].name) == 0) { + return kHashFunctions64[i].function; + } + } + return nullptr; +} + +} // namespace flatbuffers + +#endif // FLATBUFFERS_HASH_H_ diff --git a/contrib/libs/flatbuffers/include/flatbuffers/idl.h b/contrib/libs/flatbuffers/include/flatbuffers/idl.h new file mode 100644 index 0000000000..a82ff8a694 --- /dev/null +++ b/contrib/libs/flatbuffers/include/flatbuffers/idl.h @@ -0,0 +1,1208 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_IDL_H_ +#define FLATBUFFERS_IDL_H_ + +#include <map> +#include <memory> +#include <stack> + +#include "base.h" +#include "flatbuffers.h" +#include "flexbuffers.h" +#include "hash.h" +#include "reflection.h" + +#if !defined(FLATBUFFERS_CPP98_STL) +# include <functional> +#endif // !defined(FLATBUFFERS_CPP98_STL) + +// This file defines the data types representing a parsed IDL (Interface +// Definition Language) / schema file. + +// Limits maximum depth of nested objects. +// Prevents stack overflow while parse scheme, or json, or flexbuffer. +#if !defined(FLATBUFFERS_MAX_PARSING_DEPTH) +# define FLATBUFFERS_MAX_PARSING_DEPTH 64 +#endif + +namespace flatbuffers { + +// The order of these matters for Is*() functions below. +// Additionally, Parser::ParseType assumes bool..string is a contiguous range +// of type tokens. +// clang-format off +#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ + TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \ + TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) /* begin scalar/int */ \ + TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool) \ + TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8) \ + TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \ + TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16) \ + TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16) \ + TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32) \ + TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32) \ + TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64) \ + TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64) /* end int */ \ + TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32) /* begin float */ \ + TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double) /* end float/scalar */ +#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \ + TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>) \ + TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>) \ + TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>) \ + TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>) +#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \ + TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>) +// The fields are: +// - enum +// - FlatBuffers schema type. +// - C++ type. +// - Java type. +// - Go type. +// - C# / .Net type. +// - Python type. +// - Rust type. +// - Kotlin type. + +// using these macros, we can now write code dealing with types just once, e.g. + +/* +switch (type) { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ + RTYPE, KTYPE) \ + case BASE_TYPE_ ## ENUM: \ + // do something specific to CTYPE here + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD +} +*/ + +// If not all FLATBUFFERS_GEN_() arguments are necessary for implementation +// of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed). +// In the above example, only CTYPE is used to generate the code, it can be rewritten: + +/* +switch (type) { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ + case BASE_TYPE_ ## ENUM: \ + // do something specific to CTYPE here + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD +} +*/ + +#define FLATBUFFERS_GEN_TYPES(TD) \ + FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ + FLATBUFFERS_GEN_TYPES_POINTER(TD) \ + FLATBUFFERS_GEN_TYPE_ARRAY(TD) + +// Create an enum for all the types above. +#ifdef __GNUC__ +__extension__ // Stop GCC complaining about trailing comma with -Wpendantic. +#endif +enum BaseType { + #define FLATBUFFERS_TD(ENUM, ...) \ + BASE_TYPE_ ## ENUM, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD +}; + +#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ + static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \ + "define largest_scalar_t as " #CTYPE); + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) +#undef FLATBUFFERS_TD + +inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE && + t <= BASE_TYPE_DOUBLE; } +inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE && + t <= BASE_TYPE_ULONG; } +inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT || + t == BASE_TYPE_DOUBLE; } +inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG || + t == BASE_TYPE_ULONG; } +inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; } +inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE && + t <= BASE_TYPE_UCHAR; } + +inline bool IsUnsigned(BaseType t) { + return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) || + (t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) || + (t == BASE_TYPE_ULONG); +} + +// clang-format on + +extern const char *const kTypeNames[]; +extern const char kTypeSizes[]; + +inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; } + +struct StructDef; +struct EnumDef; +class Parser; + +// Represents any type in the IDL, which is a combination of the BaseType +// and additional information for vectors/structs_. +struct Type { + explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr, + EnumDef *_ed = nullptr, uint16_t _fixed_length = 0) + : base_type(_base_type), + element(BASE_TYPE_NONE), + struct_def(_sd), + enum_def(_ed), + fixed_length(_fixed_length) {} + + bool operator==(const Type &o) { + return base_type == o.base_type && element == o.element && + struct_def == o.struct_def && enum_def == o.enum_def; + } + + Type VectorType() const { + return Type(element, struct_def, enum_def, fixed_length); + } + + Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const; + + bool Deserialize(const Parser &parser, const reflection::Type *type); + + BaseType base_type; + BaseType element; // only set if t == BASE_TYPE_VECTOR + StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT + EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE, + // or for an integral type derived from an enum. + uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY +}; + +// Represents a parsed scalar value, it's type, and field offset. +struct Value { + Value() + : constant("0"), + offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {} + Type type; + std::string constant; + voffset_t offset; +}; + +// Helper class that retains the original order of a set of identifiers and +// also provides quick lookup. +template<typename T> class SymbolTable { + public: + ~SymbolTable() { + for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; } + } + + bool Add(const std::string &name, T *e) { + vector_emplace_back(&vec, e); + auto it = dict.find(name); + if (it != dict.end()) return true; + dict[name] = e; + return false; + } + + void Move(const std::string &oldname, const std::string &newname) { + auto it = dict.find(oldname); + if (it != dict.end()) { + auto obj = it->second; + dict.erase(it); + dict[newname] = obj; + } else { + FLATBUFFERS_ASSERT(false); + } + } + + T *Lookup(const std::string &name) const { + auto it = dict.find(name); + return it == dict.end() ? nullptr : it->second; + } + + public: + std::map<std::string, T *> dict; // quick lookup + std::vector<T *> vec; // Used to iterate in order of insertion +}; + +// A name space, as set in the schema. +struct Namespace { + Namespace() : from_table(0) {} + + // Given a (potentially unqualified) name, return the "fully qualified" name + // which has a full namespaced descriptor. + // With max_components you can request less than the number of components + // the current namespace has. + std::string GetFullyQualifiedName(const std::string &name, + size_t max_components = 1000) const; + + std::vector<std::string> components; + size_t from_table; // Part of the namespace corresponds to a message/table. +}; + +inline bool operator<(const Namespace &a, const Namespace &b) { + size_t min_size = std::min(a.components.size(), b.components.size()); + for (size_t i = 0; i < min_size; ++i) { + if (a.components[i] != b.components[i]) + return a.components[i] < b.components[i]; + } + return a.components.size() < b.components.size(); +} + +// Base class for all definition types (fields, structs_, enums_). +struct Definition { + Definition() + : generated(false), + defined_namespace(nullptr), + serialized_location(0), + index(-1), + refcount(1) {} + + flatbuffers::Offset< + flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> + SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const; + + bool DeserializeAttributes(Parser &parser, + const Vector<Offset<reflection::KeyValue>> *attrs); + + std::string name; + std::string file; + std::vector<std::string> doc_comment; + SymbolTable<Value> attributes; + bool generated; // did we already output code for this definition? + Namespace *defined_namespace; // Where it was defined. + + // For use with Serialize() + uoffset_t serialized_location; + int index; // Inside the vector it is stored. + int refcount; +}; + +struct FieldDef : public Definition { + FieldDef() + : deprecated(false), + key(false), + shared(false), + native_inline(false), + flexbuffer(false), + presence(kDefault), + nested_flatbuffer(NULL), + padding(0) {} + + Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id, + const Parser &parser) const; + + bool Deserialize(Parser &parser, const reflection::Field *field); + + bool IsScalarOptional() const { + return IsScalar(value.type.base_type) && IsOptional(); + } + bool IsOptional() const { + return presence == kOptional; + } + bool IsRequired() const { + return presence == kRequired; + } + bool IsDefault() const { + return presence == kDefault; + } + + Value value; + bool deprecated; // Field is allowed to be present in old data, but can't be. + // written in new data nor accessed in new code. + bool key; // Field functions as a key for creating sorted vectors. + bool shared; // Field will be using string pooling (i.e. CreateSharedString) + // as default serialization behavior if field is a string. + bool native_inline; // Field will be defined inline (instead of as a pointer) + // for native tables if field is a struct. + bool flexbuffer; // This field contains FlexBuffer data. + + enum Presence { + // Field must always be present. + kRequired, + // Non-presence should be signalled to and controlled by users. + kOptional, + // Non-presence is hidden from users. + // Implementations may omit writing default values. + kDefault, + }; + Presence static MakeFieldPresence(bool optional, bool required) { + FLATBUFFERS_ASSERT(!(required && optional)); + // clang-format off + return required ? FieldDef::kRequired + : optional ? FieldDef::kOptional + : FieldDef::kDefault; + // clang-format on + } + Presence presence; + + StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data. + size_t padding; // Bytes to always pad after this field. +}; + +struct StructDef : public Definition { + StructDef() + : fixed(false), + predecl(true), + sortbysize(true), + has_key(false), + minalign(1), + bytesize(0) {} + + void PadLastField(size_t min_align) { + auto padding = PaddingBytes(bytesize, min_align); + bytesize += padding; + if (fields.vec.size()) fields.vec.back()->padding = padding; + } + + Offset<reflection::Object> Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; + + bool Deserialize(Parser &parser, const reflection::Object *object); + + SymbolTable<FieldDef> fields; + + bool fixed; // If it's struct, not a table. + bool predecl; // If it's used before it was defined. + bool sortbysize; // Whether fields come in the declaration or size order. + bool has_key; // It has a key field. + size_t minalign; // What the whole object needs to be aligned to. + size_t bytesize; // Size if fixed. + + flatbuffers::unique_ptr<std::string> original_location; +}; + +struct EnumDef; +struct EnumValBuilder; + +struct EnumVal { + Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; + + bool Deserialize(const Parser &parser, const reflection::EnumVal *val); + + uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); } + int64_t GetAsInt64() const { return value; } + bool IsZero() const { return 0 == value; } + bool IsNonZero() const { return !IsZero(); } + + std::string name; + std::vector<std::string> doc_comment; + Type union_type; + + private: + friend EnumDef; + friend EnumValBuilder; + friend bool operator==(const EnumVal &lhs, const EnumVal &rhs); + + EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {} + EnumVal() : value(0) {} + + int64_t value; +}; + +struct EnumDef : public Definition { + EnumDef() : is_union(false), uses_multiple_type_instances(false) {} + + Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; + + bool Deserialize(Parser &parser, const reflection::Enum *values); + + template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val); + void SortByValue(); + void RemoveDuplicates(); + + std::string AllFlags() const; + const EnumVal *MinValue() const; + const EnumVal *MaxValue() const; + // Returns the number of integer steps from v1 to v2. + uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const; + // Returns the number of integer steps from Min to Max. + uint64_t Distance() const { return Distance(MinValue(), MaxValue()); } + + EnumVal *ReverseLookup(int64_t enum_idx, + bool skip_union_default = false) const; + EnumVal *FindByValue(const std::string &constant) const; + + std::string ToString(const EnumVal &ev) const { + return IsUInt64() ? NumToString(ev.GetAsUInt64()) + : NumToString(ev.GetAsInt64()); + } + + size_t size() const { return vals.vec.size(); } + + const std::vector<EnumVal *> &Vals() const { return vals.vec; } + + const EnumVal *Lookup(const std::string &enum_name) const { + return vals.Lookup(enum_name); + } + + bool is_union; + // Type is a union which uses type aliases where at least one type is + // available under two different names. + bool uses_multiple_type_instances; + Type underlying_type; + + private: + bool IsUInt64() const { + return (BASE_TYPE_ULONG == underlying_type.base_type); + } + + friend EnumValBuilder; + SymbolTable<EnumVal> vals; +}; + +inline bool IsString(const Type &type) { + return type.base_type == BASE_TYPE_STRING; +} + +inline bool IsStruct(const Type &type) { + return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed; +} + +inline bool IsUnion(const Type &type) { + return type.enum_def != nullptr && type.enum_def->is_union; +} + +inline bool IsVector(const Type &type) { + return type.base_type == BASE_TYPE_VECTOR; +} + +inline bool IsArray(const Type &type) { + return type.base_type == BASE_TYPE_ARRAY; +} + +inline bool IsSeries(const Type &type) { + return IsVector(type) || IsArray(type); +} + +inline bool IsEnum(const Type &type) { + return type.enum_def != nullptr && IsInteger(type.base_type); +} + +inline size_t InlineSize(const Type &type) { + return IsStruct(type) + ? type.struct_def->bytesize + : (IsArray(type) + ? InlineSize(type.VectorType()) * type.fixed_length + : SizeOf(type.base_type)); +} + +inline size_t InlineAlignment(const Type &type) { + if (IsStruct(type)) { + return type.struct_def->minalign; + } else if (IsArray(type)) { + return IsStruct(type.VectorType()) ? type.struct_def->minalign + : SizeOf(type.element); + } else { + return SizeOf(type.base_type); + } +} +inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) { + return lhs.value == rhs.value; +} +inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) { + return !(lhs == rhs); +} + +inline bool EqualByName(const Type &a, const Type &b) { + return a.base_type == b.base_type && a.element == b.element && + (a.struct_def == b.struct_def || + a.struct_def->name == b.struct_def->name) && + (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name); +} + +struct RPCCall : public Definition { + Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; + + bool Deserialize(Parser &parser, const reflection::RPCCall *call); + + StructDef *request, *response; +}; + +struct ServiceDef : public Definition { + Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; + bool Deserialize(Parser &parser, const reflection::Service *service); + + SymbolTable<RPCCall> calls; +}; + +// Container of options that may apply to any of the source/text generators. +struct IDLOptions { + bool gen_jvmstatic; + // Use flexbuffers instead for binary and text generation + bool use_flexbuffers; + bool strict_json; + bool output_default_scalars_in_json; + int indent_step; + bool output_enum_identifiers; + bool prefixed_enums; + bool scoped_enums; + bool include_dependence_headers; + bool mutable_buffer; + bool one_file; + bool proto_mode; + bool proto_oneof_union; + bool generate_all; + bool skip_unexpected_fields_in_json; + bool generate_name_strings; + bool generate_object_based_api; + bool gen_compare; + std::string cpp_object_api_pointer_type; + std::string cpp_object_api_string_type; + bool cpp_object_api_string_flexible_constructor; + bool cpp_direct_copy; + bool gen_nullable; + bool java_checkerframework; + bool gen_generated; + std::string object_prefix; + std::string object_suffix; + bool union_value_namespacing; + bool allow_non_utf8; + bool natural_utf8; + std::string include_prefix; + bool keep_include_path; + bool binary_schema_comments; + bool binary_schema_builtins; + bool binary_schema_gen_embed; + std::string go_import; + std::string go_namespace; + bool protobuf_ascii_alike; + bool size_prefixed; + std::string root_type; + bool force_defaults; + bool java_primitive_has_method; + bool cs_gen_json_serializer; + std::vector<std::string> cpp_includes; + std::string cpp_std; + bool cpp_static_reflection; + std::string proto_namespace_suffix; + std::string filename_suffix; + std::string filename_extension; + bool no_warnings; + + // Possible options for the more general generator below. + enum Language { + kJava = 1 << 0, + kCSharp = 1 << 1, + kGo = 1 << 2, + kCpp = 1 << 3, + kPython = 1 << 5, + kPhp = 1 << 6, + kJson = 1 << 7, + kBinary = 1 << 8, + kTs = 1 << 9, + kJsonSchema = 1 << 10, + kDart = 1 << 11, + kLua = 1 << 12, + kLobster = 1 << 13, + kRust = 1 << 14, + kKotlin = 1 << 15, + kSwift = 1 << 16, + kCppYandexMapsIter = 1 << 17, + kMAX + }; + + Language lang; + + enum MiniReflect { kNone, kTypes, kTypesAndNames }; + + MiniReflect mini_reflect; + + // If set, require all fields in a table to be explicitly numbered. + bool require_explicit_ids; + + // The corresponding language bit will be set if a language is included + // for code generation. + unsigned long lang_to_generate; + + // If set (default behavior), empty string fields will be set to nullptr to + // make the flatbuffer more compact. + bool set_empty_strings_to_null; + + // If set (default behavior), empty vector fields will be set to nullptr to + // make the flatbuffer more compact. + bool set_empty_vectors_to_null; + + IDLOptions() + : gen_jvmstatic(false), + use_flexbuffers(false), + strict_json(false), + output_default_scalars_in_json(false), + indent_step(2), + output_enum_identifiers(true), + prefixed_enums(true), + scoped_enums(false), + include_dependence_headers(true), + mutable_buffer(false), + one_file(false), + proto_mode(false), + proto_oneof_union(false), + generate_all(false), + skip_unexpected_fields_in_json(false), + generate_name_strings(false), + generate_object_based_api(false), + gen_compare(false), + cpp_object_api_pointer_type("std::unique_ptr"), + cpp_object_api_string_flexible_constructor(false), + cpp_direct_copy(true), + gen_nullable(false), + java_checkerframework(false), + gen_generated(false), + object_suffix("T"), + union_value_namespacing(true), + allow_non_utf8(false), + natural_utf8(false), + keep_include_path(false), + binary_schema_comments(false), + binary_schema_builtins(false), + binary_schema_gen_embed(false), + protobuf_ascii_alike(false), + size_prefixed(false), + force_defaults(false), + java_primitive_has_method(false), + cs_gen_json_serializer(false), + cpp_static_reflection(false), + filename_suffix("_generated"), + filename_extension(), + no_warnings(false), + lang(IDLOptions::kJava), + mini_reflect(IDLOptions::kNone), + require_explicit_ids(false), + lang_to_generate(0), + set_empty_strings_to_null(true), + set_empty_vectors_to_null(true) {} +}; + +// This encapsulates where the parser is in the current source file. +struct ParserState { + ParserState() + : cursor_(nullptr), + line_start_(nullptr), + line_(0), + token_(-1), + attr_is_trivial_ascii_string_(true) {} + + protected: + void ResetState(const char *source) { + cursor_ = source; + line_ = 0; + MarkNewLine(); + } + + void MarkNewLine() { + line_start_ = cursor_; + line_ += 1; + } + + int64_t CursorPosition() const { + FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_); + return static_cast<int64_t>(cursor_ - line_start_); + } + + const char *cursor_; + const char *line_start_; + int line_; // the current line being parsed + int token_; + + // Flag: text in attribute_ is true ASCII string without escape + // sequences. Only printable ASCII (without [\t\r\n]). + // Used for number-in-string (and base64 string in future). + bool attr_is_trivial_ascii_string_; + std::string attribute_; + std::vector<std::string> doc_comment_; +}; + +// A way to make error propagation less error prone by requiring values to be +// checked. +// Once you create a value of this type you must either: +// - Call Check() on it. +// - Copy or assign it to another value. +// Failure to do so leads to an assert. +// This guarantees that this as return value cannot be ignored. +class CheckedError { + public: + explicit CheckedError(bool error) + : is_error_(error), has_been_checked_(false) {} + + CheckedError &operator=(const CheckedError &other) { + is_error_ = other.is_error_; + has_been_checked_ = false; + other.has_been_checked_ = true; + return *this; + } + + CheckedError(const CheckedError &other) { + *this = other; // Use assignment operator. + } + + ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); } + + bool Check() { + has_been_checked_ = true; + return is_error_; + } + + private: + bool is_error_; + mutable bool has_been_checked_; +}; + +// Additionally, in GCC we can get these errors statically, for additional +// assurance: +// clang-format off +#ifdef __GNUC__ +#define FLATBUFFERS_CHECKED_ERROR CheckedError \ + __attribute__((warn_unused_result)) +#else +#define FLATBUFFERS_CHECKED_ERROR CheckedError +#endif +// clang-format on + +class Parser : public ParserState { + public: + explicit Parser(const IDLOptions &options = IDLOptions()) + : current_namespace_(nullptr), + empty_namespace_(nullptr), + flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL), + root_struct_def_(nullptr), + opts(options), + uses_flexbuffers_(false), + advanced_features_(0), + source_(nullptr), + anonymous_counter_(0), + parse_depth_counter_(0) { + if (opts.force_defaults) { builder_.ForceDefaults(true); } + // Start out with the empty namespace being current. + empty_namespace_ = new Namespace(); + namespaces_.push_back(empty_namespace_); + current_namespace_ = empty_namespace_; + known_attributes_["deprecated"] = true; + known_attributes_["required"] = true; + known_attributes_["key"] = true; + known_attributes_["shared"] = true; + known_attributes_["hash"] = true; + known_attributes_["id"] = true; + known_attributes_["force_align"] = true; + known_attributes_["bit_flags"] = true; + known_attributes_["original_order"] = true; + known_attributes_["nested_flatbuffer"] = true; + known_attributes_["csharp_partial"] = true; + known_attributes_["streaming"] = true; + known_attributes_["idempotent"] = true; + known_attributes_["cpp_type"] = true; + known_attributes_["cpp_ptr_type"] = true; + known_attributes_["cpp_ptr_type_get"] = true; + known_attributes_["cpp_str_type"] = true; + known_attributes_["cpp_str_flex_ctor"] = true; + known_attributes_["native_inline"] = true; + known_attributes_["native_custom_alloc"] = true; + known_attributes_["native_type"] = true; + known_attributes_["native_type_pack_name"] = true; + known_attributes_["native_default"] = true; + known_attributes_["flexbuffer"] = true; + known_attributes_["private"] = true; + } + + ~Parser() { + for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) { + delete *it; + } + } + + // Parse the string containing either schema or JSON data, which will + // populate the SymbolTable's or the FlatBufferBuilder above. + // include_paths is used to resolve any include statements, and typically + // should at least include the project path (where you loaded source_ from). + // include_paths must be nullptr terminated if specified. + // If include_paths is nullptr, it will attempt to load from the current + // directory. + // If the source was loaded from a file and isn't an include file, + // supply its name in source_filename. + // All paths specified in this call must be in posix format, if you accept + // paths from user input, please call PosixPath on them first. + bool Parse(const char *_source, const char **include_paths = nullptr, + const char *source_filename = nullptr); + + bool ParseJson(const char *json, const char *json_filename = nullptr); + + // Set the root type. May override the one set in the schema. + bool SetRootType(const char *name); + + // Mark all definitions as already having code generated. + void MarkGenerated(); + + // Get the files recursively included by the given file. The returned + // container will have at least the given file. + std::set<std::string> GetIncludedFilesRecursive( + const std::string &file_name) const; + + // Fills builder_ with a binary version of the schema parsed. + // See reflection/reflection.fbs + void Serialize(); + + // Deserialize a schema buffer + bool Deserialize(const uint8_t *buf, const size_t size); + + // Fills internal structure as if the schema passed had been loaded by parsing + // with Parse except that included filenames will not be populated. + bool Deserialize(const reflection::Schema *schema); + + Type *DeserializeType(const reflection::Type *type); + + // Checks that the schema represented by this parser is a safe evolution + // of the schema provided. Returns non-empty error on any problems. + std::string ConformTo(const Parser &base); + + // Similar to Parse(), but now only accepts JSON to be parsed into a + // FlexBuffer. + bool ParseFlexBuffer(const char *source, const char *source_filename, + flexbuffers::Builder *builder); + + StructDef *LookupStruct(const std::string &id) const; + StructDef *LookupStructThruParentNamespaces(const std::string &id) const; + + std::string UnqualifiedName(const std::string &fullQualifiedName); + + FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg); + + // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars + // in a schema. + // @param opts Options used to parce a schema and generate code. + static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts); + + private: + class ParseDepthGuard; + + void Message(const std::string &msg); + void Warning(const std::string &msg); + FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val); + FLATBUFFERS_CHECKED_ERROR Next(); + FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark(); + bool Is(int t) const; + bool IsIdent(const char *id) const; + FLATBUFFERS_CHECKED_ERROR Expect(int t); + std::string TokenToStringId(int t) const; + EnumDef *LookupEnum(const std::string &id); + FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id, + std::string *last); + FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type); + FLATBUFFERS_CHECKED_ERROR ParseType(Type &type); + FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def, + const std::string &name, const Type &type, + FieldDef **dest); + FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def); + FLATBUFFERS_CHECKED_ERROR ParseString(Value &val, bool use_string_pooling); + FLATBUFFERS_CHECKED_ERROR ParseComma(); + FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field, + size_t parent_fieldn, + const StructDef *parent_struct_def, + uoffset_t count, + bool inside_vector = false); + template<typename F> + FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn, + const StructDef *struct_def, + F body); + FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def, + std::string *value, uoffset_t *ovalue); + void SerializeStruct(const StructDef &struct_def, const Value &val); + void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def, + const Value &val); + template<typename F> + FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body); + FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue, + FieldDef *field, size_t fieldn); + FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array); + FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer( + Value &val, FieldDef *field, size_t fieldn, + const StructDef *parent_struct_def); + FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes); + FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, + bool check, Value &e, BaseType req, + bool *destmatch); + FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field); + FLATBUFFERS_CHECKED_ERROR TokenError(); + FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, + bool check_now); + FLATBUFFERS_CHECKED_ERROR ParseFunction(const std::string *name, Value &e); + FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, + std::string *result); + StructDef *LookupCreateStruct(const std::string &name, + bool create_if_new = true, + bool definition = false); + FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest); + FLATBUFFERS_CHECKED_ERROR ParseNamespace(); + FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name, + StructDef **dest); + FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union, + EnumDef **dest); + FLATBUFFERS_CHECKED_ERROR ParseDecl(); + FLATBUFFERS_CHECKED_ERROR ParseService(); + FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def, + bool isextend, bool inside_oneof); + FLATBUFFERS_CHECKED_ERROR ParseProtoOption(); + FLATBUFFERS_CHECKED_ERROR ParseProtoKey(); + FLATBUFFERS_CHECKED_ERROR ParseProtoDecl(); + FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent(); + FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type); + FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue(); + FLATBUFFERS_CHECKED_ERROR ParseFlexBufferNumericConstant( + flexbuffers::Builder *builder); + FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder); + FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source, + const char *source_filename); + FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source, + const char **include_paths, + const char *source_filename); + FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source, + const char **include_paths, + const char *source_filename, + const char *include_filename); + FLATBUFFERS_CHECKED_ERROR DoParseJson(); + FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef *> &fields, + StructDef *struct_def, + const char *suffix, BaseType baseType); + FLATBUFFERS_CHECKED_ERROR ParseAlignAttribute( + const std::string &align_constant, size_t min_align, size_t *align); + + bool SupportsAdvancedUnionFeatures() const; + bool SupportsAdvancedArrayFeatures() const; + bool SupportsOptionalScalars() const; + bool SupportsDefaultVectorsAndStrings() const; + Namespace *UniqueNamespace(Namespace *ns); + + FLATBUFFERS_CHECKED_ERROR RecurseError(); + template<typename F> CheckedError Recurse(F f); + + public: + SymbolTable<Type> types_; + SymbolTable<StructDef> structs_; + SymbolTable<EnumDef> enums_; + SymbolTable<ServiceDef> services_; + std::vector<Namespace *> namespaces_; + Namespace *current_namespace_; + Namespace *empty_namespace_; + std::string error_; // User readable error_ if Parse() == false + + FlatBufferBuilder builder_; // any data contained in the file + flexbuffers::Builder flex_builder_; + flexbuffers::Reference flex_root_; + StructDef *root_struct_def_; + std::string file_identifier_; + std::string file_extension_; + + std::map<uint64_t, std::string> included_files_; + std::map<std::string, std::set<std::string>> files_included_per_file_; + std::vector<std::string> native_included_files_; + + std::map<std::string, bool> known_attributes_; + + IDLOptions opts; + bool uses_flexbuffers_; + + uint64_t advanced_features_; + + private: + const char *source_; + + std::string file_being_parsed_; + + std::vector<std::pair<Value, FieldDef *>> field_stack_; + + int anonymous_counter_; + int parse_depth_counter_; // stack-overflow guard +}; + +// Utility functions for multiple generators: + +extern std::string MakeCamel(const std::string &in, bool first = true); + +extern std::string MakeScreamingCamel(const std::string &in); + +// Generate text (JSON) from a given FlatBuffer, and a given Parser +// object that has been populated with the corresponding schema. +// If ident_step is 0, no indentation will be generated. Additionally, +// if it is less than 0, no linefeeds will be generated either. +// See idl_gen_text.cpp. +// strict_json adds "quotes" around field names if true. +// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8 +// byte arrays in String values), returns false. +extern bool GenerateTextFromTable(const Parser &parser, const void *table, + const std::string &tablename, + std::string *text); +extern bool GenerateText(const Parser &parser, const void *flatbuffer, + std::string *text); +extern bool GenerateTextFile(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Json schema to string +// See idl_gen_json_schema.cpp. +extern bool GenerateJsonSchema(const Parser &parser, std::string *json); + +// Generate binary files from a given FlatBuffer, and a given Parser +// object that has been populated with the corresponding schema. +// See code_generators.cpp. +extern bool GenerateBinary(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate a C++ header from the definitions in the Parser object. +// See idl_gen_cpp. +extern bool GenerateCPP(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate C# files from the definitions in the Parser object. +// See idl_gen_csharp.cpp. +extern bool GenerateCSharp(const Parser &parser, const std::string &path, + const std::string &file_name); + +extern bool GenerateDart(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Java files from the definitions in the Parser object. +// See idl_gen_java.cpp. +extern bool GenerateJava(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate JavaScript or TypeScript code from the definitions in the Parser +// object. See idl_gen_js. +extern bool GenerateTS(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Go files from the definitions in the Parser object. +// See idl_gen_go.cpp. +extern bool GenerateGo(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Php code from the definitions in the Parser object. +// See idl_gen_php. +extern bool GeneratePhp(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Python files from the definitions in the Parser object. +// See idl_gen_python.cpp. +extern bool GeneratePython(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Lobster files from the definitions in the Parser object. +// See idl_gen_lobster.cpp. +extern bool GenerateLobster(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Lua files from the definitions in the Parser object. +// See idl_gen_lua.cpp. +extern bool GenerateLua(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Rust files from the definitions in the Parser object. +// See idl_gen_rust.cpp. +extern bool GenerateRust(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Json schema file +// See idl_gen_json_schema.cpp. +extern bool GenerateJsonSchema(const Parser &parser, const std::string &path, + const std::string &file_name); + +extern bool GenerateKotlin(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate Swift classes. +// See idl_gen_swift.cpp +extern bool GenerateSwift(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate a schema file from the internal representation, useful after +// parsing a .proto schema. +extern std::string GenerateFBS(const Parser &parser, + const std::string &file_name); +extern bool GenerateFBS(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate a C++ header for reading with templated file iterator from +// the definitions in the Parser object. +// See idl_gen_cpp_yandex_maps_iter.cpp. +extern std::string GenerateCPPYandexMapsIter(const Parser &parser, + const std::string &include_guard_ident); +extern bool GenerateCPPYandexMapsIter(const Parser &parser, + const std::string &path, + const std::string &file_name); + +// Generate a make rule for the generated TypeScript code. +// See idl_gen_ts.cpp. +extern std::string TSMakeRule(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate a make rule for the generated C++ header. +// See idl_gen_cpp.cpp. +extern std::string CPPMakeRule(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate a make rule for the generated Dart code +// see idl_gen_dart.cpp +extern std::string DartMakeRule(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate a make rule for the generated Rust code. +// See idl_gen_rust.cpp. +extern std::string RustMakeRule(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate a make rule for generated Java or C# files. +// See code_generators.cpp. +extern std::string JavaCSharpMakeRule(const Parser &parser, + const std::string &path, + const std::string &file_name); + +// Generate a make rule for the generated text (JSON) files. +// See idl_gen_text.cpp. +extern std::string TextMakeRule(const Parser &parser, const std::string &path, + const std::string &file_names); + +// Generate a make rule for the generated binary files. +// See code_generators.cpp. +extern std::string BinaryMakeRule(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate GRPC Cpp interfaces. +// See idl_gen_grpc.cpp. +bool GenerateCppGRPC(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate GRPC Go interfaces. +// See idl_gen_grpc.cpp. +bool GenerateGoGRPC(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate GRPC Java classes. +// See idl_gen_grpc.cpp +bool GenerateJavaGRPC(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate GRPC Python interfaces. +// See idl_gen_grpc.cpp. +bool GeneratePythonGRPC(const Parser &parser, const std::string &path, + const std::string &file_name); + +// Generate GRPC Swift interfaces. +// See idl_gen_grpc.cpp. +extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path, + const std::string &file_name); + +extern bool GenerateTSGRPC(const Parser &parser, const std::string &path, + const std::string &file_name); +} // namespace flatbuffers + +#endif // FLATBUFFERS_IDL_H_ diff --git a/contrib/libs/flatbuffers/include/flatbuffers/reflection.h b/contrib/libs/flatbuffers/include/flatbuffers/reflection.h new file mode 100644 index 0000000000..d268a3ffea --- /dev/null +++ b/contrib/libs/flatbuffers/include/flatbuffers/reflection.h @@ -0,0 +1,502 @@ +/* + * Copyright 2015 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_REFLECTION_H_ +#define FLATBUFFERS_REFLECTION_H_ + +// This is somewhat of a circular dependency because flatc (and thus this +// file) is needed to generate this header in the first place. +// Should normally not be a problem since it can be generated by the +// previous version of flatc whenever this code needs to change. +// See reflection/generate_code.sh +#include "reflection_generated.h" + +// Helper functionality for reflection. + +namespace flatbuffers { + +// ------------------------- GETTERS ------------------------- + +inline bool IsScalar(reflection::BaseType t) { + return t >= reflection::UType && t <= reflection::Double; +} +inline bool IsInteger(reflection::BaseType t) { + return t >= reflection::UType && t <= reflection::ULong; +} +inline bool IsFloat(reflection::BaseType t) { + 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. +inline size_t GetTypeSize(reflection::BaseType base_type) { + // This needs to correspond to the BaseType enum. + static size_t sizes[] = { + 0, // None + 1, // UType + 1, // Bool + 1, // Byte + 1, // UByte + 2, // Short + 2, // UShort + 4, // Int + 4, // UInt + 8, // Long + 8, // ULong + 4, // Float + 8, // Double + 4, // String + 4, // Vector + 4, // Obj + 4, // Union + 0, // Array. Only used in structs. 0 was chosen to prevent out-of-bounds + // errors. + + 0 // MaxBaseType. This must be kept the last entry in this array. + }; + static_assert(sizeof(sizes) / sizeof(size_t) == reflection::MaxBaseType + 1, + "Size of sizes[] array does not match the count of BaseType " + "enum values."); + return sizes[base_type]; +} + +// Same as above, but now correctly returns the size of a struct if +// the field (or vector element) is a struct. +inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index, + const reflection::Schema &schema) { + if (base_type == reflection::Obj && + schema.objects()->Get(type_index)->is_struct()) { + return schema.objects()->Get(type_index)->bytesize(); + } else { + return GetTypeSize(base_type); + } +} + +// Get the root, regardless of what type it is. +inline Table *GetAnyRoot(uint8_t *flatbuf) { + return GetMutableRoot<Table>(flatbuf); +} +inline const Table *GetAnyRoot(const uint8_t *flatbuf) { + return GetRoot<Table>(flatbuf); +} + +// Get a field's default, if you know it's an integer, and its exact type. +template<typename T> T GetFieldDefaultI(const reflection::Field &field) { + FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type())); + return static_cast<T>(field.default_integer()); +} + +// Get a field's default, if you know it's floating point and its exact type. +template<typename T> T GetFieldDefaultF(const reflection::Field &field) { + FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type())); + return static_cast<T>(field.default_real()); +} + +// Get a field, if you know it's an integer, and its exact type. +template<typename T> +T GetFieldI(const Table &table, const reflection::Field &field) { + FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type())); + return table.GetField<T>(field.offset(), + static_cast<T>(field.default_integer())); +} + +// Get a field, if you know it's floating point and its exact type. +template<typename T> +T GetFieldF(const Table &table, const reflection::Field &field) { + FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type())); + return table.GetField<T>(field.offset(), + static_cast<T>(field.default_real())); +} + +// Get a field, if you know it's a string. +inline const String *GetFieldS(const Table &table, + const reflection::Field &field) { + FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::String); + return table.GetPointer<const String *>(field.offset()); +} + +// Get a field, if you know it's a vector. +template<typename T> +Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) { + FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Vector && + sizeof(T) == GetTypeSize(field.type()->element())); + return table.GetPointer<Vector<T> *>(field.offset()); +} + +// Get a field, if you know it's a vector, generically. +// To actually access elements, use the return value together with +// field.type()->element() in any of GetAnyVectorElemI below etc. +inline VectorOfAny *GetFieldAnyV(const Table &table, + const reflection::Field &field) { + return table.GetPointer<VectorOfAny *>(field.offset()); +} + +// Get a field, if you know it's a table. +inline Table *GetFieldT(const Table &table, const reflection::Field &field) { + FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj || + field.type()->base_type() == reflection::Union); + return table.GetPointer<Table *>(field.offset()); +} + +// Get a field, if you know it's a struct. +inline const Struct *GetFieldStruct(const Table &table, + const reflection::Field &field) { + // TODO: This does NOT check if the field is a table or struct, but we'd need + // access to the schema to check the is_struct flag. + FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj); + return table.GetStruct<const Struct *>(field.offset()); +} + +// Get a structure's field, if you know it's a struct. +inline const Struct *GetFieldStruct(const Struct &structure, + const reflection::Field &field) { + FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj); + return structure.GetStruct<const Struct *>(field.offset()); +} + +// Raw helper functions used below: get any value in memory as a 64bit int, a +// double or a string. +// All scalars get static_cast to an int64_t, strings use strtoull, every other +// data type returns 0. +int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data); +// All scalars static cast to double, strings use strtod, every other data +// type is 0.0. +double GetAnyValueF(reflection::BaseType type, const uint8_t *data); +// All scalars converted using stringstream, strings as-is, and all other +// data types provide some level of debug-pretty-printing. +std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data, + const reflection::Schema *schema, int type_index); + +// Get any table field as a 64bit int, regardless of what type it is. +inline int64_t GetAnyFieldI(const Table &table, + const reflection::Field &field) { + auto field_ptr = table.GetAddressOf(field.offset()); + return field_ptr ? GetAnyValueI(field.type()->base_type(), field_ptr) + : field.default_integer(); +} + +// Get any table field as a double, regardless of what type it is. +inline double GetAnyFieldF(const Table &table, const reflection::Field &field) { + auto field_ptr = table.GetAddressOf(field.offset()); + return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr) + : field.default_real(); +} + +// 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 +// are of table type pretty-printed. +inline std::string GetAnyFieldS(const Table &table, + const reflection::Field &field, + const reflection::Schema *schema) { + auto field_ptr = table.GetAddressOf(field.offset()); + return field_ptr ? GetAnyValueS(field.type()->base_type(), field_ptr, schema, + field.type()->index()) + : ""; +} + +// Get any struct field as a 64bit int, regardless of what type it is. +inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field) { + return GetAnyValueI(field.type()->base_type(), + st.GetAddressOf(field.offset())); +} + +// Get any struct field as a double, regardless of what type it is. +inline double GetAnyFieldF(const Struct &st, const reflection::Field &field) { + return GetAnyValueF(field.type()->base_type(), + st.GetAddressOf(field.offset())); +} + +// Get any struct field as a string, regardless of what type it is. +inline std::string GetAnyFieldS(const Struct &st, + const reflection::Field &field) { + return GetAnyValueS(field.type()->base_type(), + st.GetAddressOf(field.offset()), nullptr, -1); +} + +// Get any vector element as a 64bit int, regardless of what type it is. +inline int64_t GetAnyVectorElemI(const VectorOfAny *vec, + reflection::BaseType elem_type, size_t i) { + return GetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i); +} + +// Get any vector element as a double, regardless of what type it is. +inline double GetAnyVectorElemF(const VectorOfAny *vec, + reflection::BaseType elem_type, size_t i) { + return GetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i); +} + +// Get any vector element as a string, regardless of what type it is. +inline std::string GetAnyVectorElemS(const VectorOfAny *vec, + reflection::BaseType elem_type, size_t i) { + return GetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, + nullptr, -1); +} + +// Get a vector element that's a table/string/vector from a generic vector. +// Pass Table/String/VectorOfAny as template parameter. +// Warning: does no typechecking. +template<typename T> +T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) { + auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i; + return reinterpret_cast<T *>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr)); +} + +// Get the inline-address of a vector element. Useful for Structs (pass Struct +// as template arg), or being able to address a range of scalars in-line. +// Get elem_size from GetTypeSizeInline(). +// Note: little-endian data on all platforms, use EndianScalar() instead of +// raw pointer access with scalars). +template<typename T> +T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i, + size_t elem_size) { + return reinterpret_cast<T *>(vec->Data() + elem_size * i); +} + +// Similarly, for elements of tables. +template<typename T> +T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) { + return reinterpret_cast<T *>(table.GetAddressOf(field.offset())); +} + +// Similarly, for elements of structs. +template<typename T> +T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) { + return reinterpret_cast<T *>(st.GetAddressOf(field.offset())); +} + +// ------------------------- SETTERS ------------------------- + +// Set any scalar field, if you know its exact type. +template<typename T> +bool SetField(Table *table, const reflection::Field &field, T val) { + reflection::BaseType type = field.type()->base_type(); + if (!IsScalar(type)) { return false; } + FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(type)); + T def; + if (IsInteger(type)) { + def = GetFieldDefaultI<T>(field); + } else { + FLATBUFFERS_ASSERT(IsFloat(type)); + def = GetFieldDefaultF<T>(field); + } + return table->SetField(field.offset(), val, def); +} + +// Raw helper functions used below: set any value in memory as a 64bit int, a +// double or a string. +// These work for all scalar values, but do nothing for other data types. +// To set a string, see SetString below. +void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val); +void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val); +void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val); + +// Set any table field as a 64bit int, regardless of type what it is. +inline bool SetAnyFieldI(Table *table, const reflection::Field &field, + int64_t val) { + auto field_ptr = table->GetAddressOf(field.offset()); + if (!field_ptr) return val == GetFieldDefaultI<int64_t>(field); + SetAnyValueI(field.type()->base_type(), field_ptr, val); + return true; +} + +// Set any table field as a double, regardless of what type it is. +inline bool SetAnyFieldF(Table *table, const reflection::Field &field, + double val) { + auto field_ptr = table->GetAddressOf(field.offset()); + if (!field_ptr) return val == GetFieldDefaultF<double>(field); + SetAnyValueF(field.type()->base_type(), field_ptr, val); + return true; +} + +// Set any table field as a string, regardless of what type it is. +inline bool SetAnyFieldS(Table *table, const reflection::Field &field, + const char *val) { + auto field_ptr = table->GetAddressOf(field.offset()); + if (!field_ptr) return false; + SetAnyValueS(field.type()->base_type(), field_ptr, val); + return true; +} + +// Set any struct field as a 64bit int, regardless of type what it is. +inline void SetAnyFieldI(Struct *st, const reflection::Field &field, + int64_t val) { + SetAnyValueI(field.type()->base_type(), st->GetAddressOf(field.offset()), + val); +} + +// Set any struct field as a double, regardless of type what it is. +inline void SetAnyFieldF(Struct *st, const reflection::Field &field, + double val) { + SetAnyValueF(field.type()->base_type(), st->GetAddressOf(field.offset()), + val); +} + +// Set any struct field as a string, regardless of type what it is. +inline void SetAnyFieldS(Struct *st, const reflection::Field &field, + const char *val) { + SetAnyValueS(field.type()->base_type(), st->GetAddressOf(field.offset()), + val); +} + +// Set any vector element as a 64bit int, regardless of type what it is. +inline void SetAnyVectorElemI(VectorOfAny *vec, reflection::BaseType elem_type, + size_t i, int64_t val) { + SetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val); +} + +// Set any vector element as a double, regardless of type what it is. +inline void SetAnyVectorElemF(VectorOfAny *vec, reflection::BaseType elem_type, + size_t i, double val) { + SetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val); +} + +// Set any vector element as a string, regardless of type what it is. +inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type, + size_t i, const char *val) { + SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val); +} + +// ------------------------- RESIZING SETTERS ------------------------- + +// "smart" pointer for use with resizing vectors: turns a pointer inside +// a vector into a relative offset, such that it is not affected by resizes. +template<typename T, typename U> class pointer_inside_vector { + public: + pointer_inside_vector(T *ptr, std::vector<U> &vec) + : offset_(reinterpret_cast<uint8_t *>(ptr) - + reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))), + vec_(vec) {} + + T *operator*() const { + return reinterpret_cast<T *>( + reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) + offset_); + } + T *operator->() const { return operator*(); } + + private: + size_t offset_; + std::vector<U> &vec_; +}; + +// Helper to create the above easily without specifying template args. +template<typename T, typename U> +pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec) { + return pointer_inside_vector<T, U>(ptr, vec); +} + +inline const char *UnionTypeFieldSuffix() { return "_type"; } + +// Helper to figure out the actual table type a union refers to. +inline const reflection::Object &GetUnionType( + const reflection::Schema &schema, const reflection::Object &parent, + const reflection::Field &unionfield, const Table &table) { + auto enumdef = schema.enums()->Get(unionfield.type()->index()); + // TODO: this is clumsy and slow, but no other way to find it? + auto type_field = parent.fields()->LookupByKey( + (unionfield.name()->str() + UnionTypeFieldSuffix()).c_str()); + FLATBUFFERS_ASSERT(type_field); + auto union_type = GetFieldI<uint8_t>(table, *type_field); + auto enumval = enumdef->values()->LookupByKey(union_type); + return *enumval->object(); +} + +// Changes the contents of a string inside a FlatBuffer. FlatBuffer must +// live inside a std::vector so we can resize the buffer if needed. +// "str" must live inside "flatbuf" and may be invalidated after this call. +// If your FlatBuffer's root table is not the schema's root table, you should +// pass in your root_table type as well. +void SetString(const reflection::Schema &schema, const std::string &val, + const String *str, std::vector<uint8_t> *flatbuf, + const reflection::Object *root_table = nullptr); + +// Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must +// live inside a std::vector so we can resize the buffer if needed. +// "vec" must live inside "flatbuf" and may be invalidated after this call. +// If your FlatBuffer's root table is not the schema's root table, you should +// pass in your root_table type as well. +uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize, + const VectorOfAny *vec, uoffset_t num_elems, + uoffset_t elem_size, std::vector<uint8_t> *flatbuf, + const reflection::Object *root_table = nullptr); + +template<typename T> +void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val, + const Vector<T> *vec, std::vector<uint8_t> *flatbuf, + const reflection::Object *root_table = nullptr) { + auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size()); + auto newelems = ResizeAnyVector( + schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(), + static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table); + // Set new elements to "val". + for (int i = 0; i < delta_elem; i++) { + auto loc = newelems + i * sizeof(T); + auto is_scalar = flatbuffers::is_scalar<T>::value; + if (is_scalar) { + WriteScalar(loc, val); + } else { // struct + *reinterpret_cast<T *>(loc) = val; + } + } +} + +// Adds any new data (in the form of a new FlatBuffer) to an existing +// FlatBuffer. This can be used when any of the above methods are not +// sufficient, in particular for adding new tables and new fields. +// This is potentially slightly less efficient than a FlatBuffer constructed +// in one piece, since the new FlatBuffer doesn't share any vtables with the +// existing one. +// The return value can now be set using Vector::MutateOffset or SetFieldT +// below. +const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf, + const uint8_t *newbuf, size_t newlen); + +inline bool SetFieldT(Table *table, const reflection::Field &field, + const uint8_t *val) { + FLATBUFFERS_ASSERT(sizeof(uoffset_t) == + GetTypeSize(field.type()->base_type())); + return table->SetPointer(field.offset(), val); +} + +// ------------------------- COPYING ------------------------- + +// Generic copying of tables from a FlatBuffer into a FlatBuffer builder. +// Can be used to do any kind of merging/selecting you may want to do out +// of existing buffers. Also useful to reconstruct a whole buffer if the +// above resizing functionality has introduced garbage in a buffer you want +// to remove. +// Note: this does not deal with DAGs correctly. If the table passed forms a +// DAG, the copy will be a tree instead (with duplicates). Strings can be +// shared however, by passing true for use_string_pooling. + +Offset<const Table *> CopyTable(FlatBufferBuilder &fbb, + const reflection::Schema &schema, + const reflection::Object &objectdef, + const Table &table, + bool use_string_pooling = false); + +// Verifies the provided flatbuffer using reflection. +// root should point to the root type for this flatbuffer. +// buf should point to the start of flatbuffer data. +// length specifies the size of the flatbuffer data. +bool Verify(const reflection::Schema &schema, const reflection::Object &root, + const uint8_t *buf, size_t length, uoffset_t max_depth = 64, + uoffset_t max_tables = 1000000); + +} // namespace flatbuffers + +#endif // FLATBUFFERS_REFLECTION_H_ diff --git a/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h b/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h new file mode 100644 index 0000000000..93dc4b88b7 --- /dev/null +++ b/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h @@ -0,0 +1,1278 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_ +#define FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_ + +#include "flatbuffers.h" + +namespace reflection { + +struct Type; +struct TypeBuilder; + +struct KeyValue; +struct KeyValueBuilder; + +struct EnumVal; +struct EnumValBuilder; + +struct Enum; +struct EnumBuilder; + +struct Field; +struct FieldBuilder; + +struct Object; +struct ObjectBuilder; + +struct RPCCall; +struct RPCCallBuilder; + +struct Service; +struct ServiceBuilder; + +struct Schema; +struct SchemaBuilder; + +enum BaseType { + None = 0, + UType = 1, + Bool = 2, + Byte = 3, + UByte = 4, + Short = 5, + UShort = 6, + Int = 7, + UInt = 8, + Long = 9, + ULong = 10, + Float = 11, + Double = 12, + String = 13, + Vector = 14, + Obj = 15, + Union = 16, + Array = 17, + MaxBaseType = 18 +}; + +inline const BaseType (&EnumValuesBaseType())[19] { + static const BaseType values[] = { + None, + UType, + Bool, + Byte, + UByte, + Short, + UShort, + Int, + UInt, + Long, + ULong, + Float, + Double, + String, + Vector, + Obj, + Union, + Array, + MaxBaseType + }; + return values; +} + +inline const char * const *EnumNamesBaseType() { + static const char * const names[20] = { + "None", + "UType", + "Bool", + "Byte", + "UByte", + "Short", + "UShort", + "Int", + "UInt", + "Long", + "ULong", + "Float", + "Double", + "String", + "Vector", + "Obj", + "Union", + "Array", + "MaxBaseType", + nullptr + }; + return names; +} + +inline const char *EnumNameBaseType(BaseType e) { + if (flatbuffers::IsOutRange(e, None, MaxBaseType)) return ""; + const size_t index = static_cast<size_t>(e); + return EnumNamesBaseType()[index]; +} + +enum AdvancedFeatures { + AdvancedArrayFeatures = 1ULL, + AdvancedUnionFeatures = 2ULL, + OptionalScalars = 4ULL, + DefaultVectorsAndStrings = 8ULL +}; + +inline const AdvancedFeatures (&EnumValuesAdvancedFeatures())[4] { + static const AdvancedFeatures values[] = { + AdvancedArrayFeatures, + AdvancedUnionFeatures, + OptionalScalars, + DefaultVectorsAndStrings + }; + return values; +} + +inline const char * const *EnumNamesAdvancedFeatures() { + static const char * const names[9] = { + "AdvancedArrayFeatures", + "AdvancedUnionFeatures", + "", + "OptionalScalars", + "", + "", + "", + "DefaultVectorsAndStrings", + nullptr + }; + return names; +} + +inline const char *EnumNameAdvancedFeatures(AdvancedFeatures e) { + if (flatbuffers::IsOutRange(e, AdvancedArrayFeatures, DefaultVectorsAndStrings)) return ""; + const size_t index = static_cast<size_t>(e) - static_cast<size_t>(AdvancedArrayFeatures); + return EnumNamesAdvancedFeatures()[index]; +} + +struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TypeBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_BASE_TYPE = 4, + VT_ELEMENT = 6, + VT_INDEX = 8, + VT_FIXED_LENGTH = 10 + }; + reflection::BaseType base_type() const { + return static_cast<reflection::BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0)); + } + reflection::BaseType element() const { + return static_cast<reflection::BaseType>(GetField<int8_t>(VT_ELEMENT, 0)); + } + int32_t index() const { + return GetField<int32_t>(VT_INDEX, -1); + } + uint16_t fixed_length() const { + return GetField<uint16_t>(VT_FIXED_LENGTH, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<int8_t>(verifier, VT_BASE_TYPE) && + VerifyField<int8_t>(verifier, VT_ELEMENT) && + VerifyField<int32_t>(verifier, VT_INDEX) && + VerifyField<uint16_t>(verifier, VT_FIXED_LENGTH) && + verifier.EndTable(); + } +}; + +struct TypeBuilder { + typedef Type Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_base_type(reflection::BaseType base_type) { + fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0); + } + void add_element(reflection::BaseType element) { + fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0); + } + void add_index(int32_t index) { + fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1); + } + void add_fixed_length(uint16_t fixed_length) { + fbb_.AddElement<uint16_t>(Type::VT_FIXED_LENGTH, fixed_length, 0); + } + explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<Type> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<Type>(end); + return o; + } +}; + +inline flatbuffers::Offset<Type> CreateType( + flatbuffers::FlatBufferBuilder &_fbb, + reflection::BaseType base_type = reflection::None, + reflection::BaseType element = reflection::None, + int32_t index = -1, + uint16_t fixed_length = 0) { + TypeBuilder builder_(_fbb); + builder_.add_index(index); + builder_.add_fixed_length(fixed_length); + builder_.add_element(element); + builder_.add_base_type(base_type); + return builder_.Finish(); +} + +struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef KeyValueBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_KEY = 4, + VT_VALUE = 6 + }; + const flatbuffers::String *key() const { + return GetPointer<const flatbuffers::String *>(VT_KEY); + } + bool KeyCompareLessThan(const KeyValue *o) const { + return *key() < *o->key(); + } + int KeyCompareWithValue(const char *val) const { + return strcmp(key()->c_str(), val); + } + const flatbuffers::String *value() const { + return GetPointer<const flatbuffers::String *>(VT_VALUE); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffsetRequired(verifier, VT_KEY) && + verifier.VerifyString(key()) && + VerifyOffset(verifier, VT_VALUE) && + verifier.VerifyString(value()) && + verifier.EndTable(); + } +}; + +struct KeyValueBuilder { + typedef KeyValue Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_key(flatbuffers::Offset<flatbuffers::String> key) { + fbb_.AddOffset(KeyValue::VT_KEY, key); + } + void add_value(flatbuffers::Offset<flatbuffers::String> value) { + fbb_.AddOffset(KeyValue::VT_VALUE, value); + } + explicit KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<KeyValue> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<KeyValue>(end); + fbb_.Required(o, KeyValue::VT_KEY); + return o; + } +}; + +inline flatbuffers::Offset<KeyValue> CreateKeyValue( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::String> key = 0, + flatbuffers::Offset<flatbuffers::String> value = 0) { + KeyValueBuilder builder_(_fbb); + builder_.add_value(value); + builder_.add_key(key); + return builder_.Finish(); +} + +inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *key = nullptr, + const char *value = nullptr) { + auto key__ = key ? _fbb.CreateString(key) : 0; + auto value__ = value ? _fbb.CreateString(value) : 0; + return reflection::CreateKeyValue( + _fbb, + key__, + value__); +} + +struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef EnumValBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NAME = 4, + VT_VALUE = 6, + VT_OBJECT = 8, + VT_UNION_TYPE = 10, + VT_DOCUMENTATION = 12 + }; + const flatbuffers::String *name() const { + return GetPointer<const flatbuffers::String *>(VT_NAME); + } + int64_t value() const { + return GetField<int64_t>(VT_VALUE, 0); + } + bool KeyCompareLessThan(const EnumVal *o) const { + return value() < o->value(); + } + int KeyCompareWithValue(int64_t val) const { + return static_cast<int>(value() > val) - static_cast<int>(value() < val); + } + const reflection::Object *object() const { + return GetPointer<const reflection::Object *>(VT_OBJECT); + } + const reflection::Type *union_type() const { + return GetPointer<const reflection::Type *>(VT_UNION_TYPE); + } + const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffsetRequired(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyField<int64_t>(verifier, VT_VALUE) && + VerifyOffset(verifier, VT_OBJECT) && + verifier.VerifyTable(object()) && + VerifyOffset(verifier, VT_UNION_TYPE) && + verifier.VerifyTable(union_type()) && + VerifyOffset(verifier, VT_DOCUMENTATION) && + verifier.VerifyVector(documentation()) && + verifier.VerifyVectorOfStrings(documentation()) && + verifier.EndTable(); + } +}; + +struct EnumValBuilder { + typedef EnumVal Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_name(flatbuffers::Offset<flatbuffers::String> name) { + fbb_.AddOffset(EnumVal::VT_NAME, name); + } + void add_value(int64_t value) { + fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0); + } + void add_object(flatbuffers::Offset<reflection::Object> object) { + fbb_.AddOffset(EnumVal::VT_OBJECT, object); + } + void add_union_type(flatbuffers::Offset<reflection::Type> union_type) { + fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type); + } + void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { + fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation); + } + explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<EnumVal> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<EnumVal>(end); + fbb_.Required(o, EnumVal::VT_NAME); + return o; + } +}; + +inline flatbuffers::Offset<EnumVal> CreateEnumVal( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::String> name = 0, + int64_t value = 0, + flatbuffers::Offset<reflection::Object> object = 0, + flatbuffers::Offset<reflection::Type> union_type = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) { + EnumValBuilder builder_(_fbb); + builder_.add_value(value); + builder_.add_documentation(documentation); + builder_.add_union_type(union_type); + builder_.add_object(object); + builder_.add_name(name); + return builder_.Finish(); +} + +inline flatbuffers::Offset<EnumVal> CreateEnumValDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *name = nullptr, + int64_t value = 0, + flatbuffers::Offset<reflection::Object> object = 0, + flatbuffers::Offset<reflection::Type> union_type = 0, + const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { + auto name__ = name ? _fbb.CreateString(name) : 0; + auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; + return reflection::CreateEnumVal( + _fbb, + name__, + value, + object, + union_type, + documentation__); +} + +struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef EnumBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NAME = 4, + VT_VALUES = 6, + VT_IS_UNION = 8, + VT_UNDERLYING_TYPE = 10, + VT_ATTRIBUTES = 12, + VT_DOCUMENTATION = 14 + }; + const flatbuffers::String *name() const { + return GetPointer<const flatbuffers::String *>(VT_NAME); + } + bool KeyCompareLessThan(const Enum *o) const { + return *name() < *o->name(); + } + int KeyCompareWithValue(const char *val) const { + return strcmp(name()->c_str(), val); + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *values() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *>(VT_VALUES); + } + bool is_union() const { + return GetField<uint8_t>(VT_IS_UNION, 0) != 0; + } + const reflection::Type *underlying_type() const { + return GetPointer<const reflection::Type *>(VT_UNDERLYING_TYPE); + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES); + } + const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffsetRequired(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyOffsetRequired(verifier, VT_VALUES) && + verifier.VerifyVector(values()) && + verifier.VerifyVectorOfTables(values()) && + VerifyField<uint8_t>(verifier, VT_IS_UNION) && + VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) && + verifier.VerifyTable(underlying_type()) && + VerifyOffset(verifier, VT_ATTRIBUTES) && + verifier.VerifyVector(attributes()) && + verifier.VerifyVectorOfTables(attributes()) && + VerifyOffset(verifier, VT_DOCUMENTATION) && + verifier.VerifyVector(documentation()) && + verifier.VerifyVectorOfStrings(documentation()) && + verifier.EndTable(); + } +}; + +struct EnumBuilder { + typedef Enum Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_name(flatbuffers::Offset<flatbuffers::String> name) { + fbb_.AddOffset(Enum::VT_NAME, name); + } + void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values) { + fbb_.AddOffset(Enum::VT_VALUES, values); + } + void add_is_union(bool is_union) { + fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0); + } + void add_underlying_type(flatbuffers::Offset<reflection::Type> underlying_type) { + fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type); + } + void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) { + fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes); + } + void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { + fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation); + } + explicit EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<Enum> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<Enum>(end); + fbb_.Required(o, Enum::VT_NAME); + fbb_.Required(o, Enum::VT_VALUES); + fbb_.Required(o, Enum::VT_UNDERLYING_TYPE); + return o; + } +}; + +inline flatbuffers::Offset<Enum> CreateEnum( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::String> name = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values = 0, + bool is_union = false, + flatbuffers::Offset<reflection::Type> underlying_type = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) { + EnumBuilder builder_(_fbb); + builder_.add_documentation(documentation); + builder_.add_attributes(attributes); + builder_.add_underlying_type(underlying_type); + builder_.add_values(values); + builder_.add_name(name); + builder_.add_is_union(is_union); + return builder_.Finish(); +} + +inline flatbuffers::Offset<Enum> CreateEnumDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *name = nullptr, + std::vector<flatbuffers::Offset<reflection::EnumVal>> *values = nullptr, + bool is_union = false, + flatbuffers::Offset<reflection::Type> underlying_type = 0, + std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr, + const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { + auto name__ = name ? _fbb.CreateString(name) : 0; + auto values__ = values ? _fbb.CreateVectorOfSortedTables<reflection::EnumVal>(values) : 0; + auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0; + auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; + return reflection::CreateEnum( + _fbb, + name__, + values__, + is_union, + underlying_type, + attributes__, + documentation__); +} + +struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FieldBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NAME = 4, + VT_TYPE = 6, + VT_ID = 8, + VT_OFFSET = 10, + VT_DEFAULT_INTEGER = 12, + VT_DEFAULT_REAL = 14, + VT_DEPRECATED = 16, + VT_REQUIRED = 18, + VT_KEY = 20, + VT_ATTRIBUTES = 22, + VT_DOCUMENTATION = 24, + VT_OPTIONAL = 26 + }; + const flatbuffers::String *name() const { + return GetPointer<const flatbuffers::String *>(VT_NAME); + } + bool KeyCompareLessThan(const Field *o) const { + return *name() < *o->name(); + } + int KeyCompareWithValue(const char *val) const { + return strcmp(name()->c_str(), val); + } + const reflection::Type *type() const { + return GetPointer<const reflection::Type *>(VT_TYPE); + } + uint16_t id() const { + return GetField<uint16_t>(VT_ID, 0); + } + uint16_t offset() const { + return GetField<uint16_t>(VT_OFFSET, 0); + } + int64_t default_integer() const { + return GetField<int64_t>(VT_DEFAULT_INTEGER, 0); + } + double default_real() const { + return GetField<double>(VT_DEFAULT_REAL, 0.0); + } + bool deprecated() const { + return GetField<uint8_t>(VT_DEPRECATED, 0) != 0; + } + bool required() const { + return GetField<uint8_t>(VT_REQUIRED, 0) != 0; + } + bool key() const { + return GetField<uint8_t>(VT_KEY, 0) != 0; + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES); + } + const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION); + } + bool optional() const { + return GetField<uint8_t>(VT_OPTIONAL, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffsetRequired(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyOffsetRequired(verifier, VT_TYPE) && + verifier.VerifyTable(type()) && + VerifyField<uint16_t>(verifier, VT_ID) && + VerifyField<uint16_t>(verifier, VT_OFFSET) && + VerifyField<int64_t>(verifier, VT_DEFAULT_INTEGER) && + VerifyField<double>(verifier, VT_DEFAULT_REAL) && + VerifyField<uint8_t>(verifier, VT_DEPRECATED) && + VerifyField<uint8_t>(verifier, VT_REQUIRED) && + VerifyField<uint8_t>(verifier, VT_KEY) && + VerifyOffset(verifier, VT_ATTRIBUTES) && + verifier.VerifyVector(attributes()) && + verifier.VerifyVectorOfTables(attributes()) && + VerifyOffset(verifier, VT_DOCUMENTATION) && + verifier.VerifyVector(documentation()) && + verifier.VerifyVectorOfStrings(documentation()) && + VerifyField<uint8_t>(verifier, VT_OPTIONAL) && + verifier.EndTable(); + } +}; + +struct FieldBuilder { + typedef Field Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_name(flatbuffers::Offset<flatbuffers::String> name) { + fbb_.AddOffset(Field::VT_NAME, name); + } + void add_type(flatbuffers::Offset<reflection::Type> type) { + fbb_.AddOffset(Field::VT_TYPE, type); + } + void add_id(uint16_t id) { + fbb_.AddElement<uint16_t>(Field::VT_ID, id, 0); + } + void add_offset(uint16_t offset) { + fbb_.AddElement<uint16_t>(Field::VT_OFFSET, offset, 0); + } + void add_default_integer(int64_t default_integer) { + fbb_.AddElement<int64_t>(Field::VT_DEFAULT_INTEGER, default_integer, 0); + } + void add_default_real(double default_real) { + fbb_.AddElement<double>(Field::VT_DEFAULT_REAL, default_real, 0.0); + } + void add_deprecated(bool deprecated) { + fbb_.AddElement<uint8_t>(Field::VT_DEPRECATED, static_cast<uint8_t>(deprecated), 0); + } + void add_required(bool required) { + fbb_.AddElement<uint8_t>(Field::VT_REQUIRED, static_cast<uint8_t>(required), 0); + } + void add_key(bool key) { + fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0); + } + void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) { + fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes); + } + void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { + fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation); + } + void add_optional(bool optional) { + fbb_.AddElement<uint8_t>(Field::VT_OPTIONAL, static_cast<uint8_t>(optional), 0); + } + explicit FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<Field> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<Field>(end); + fbb_.Required(o, Field::VT_NAME); + fbb_.Required(o, Field::VT_TYPE); + return o; + } +}; + +inline flatbuffers::Offset<Field> CreateField( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::String> name = 0, + flatbuffers::Offset<reflection::Type> type = 0, + uint16_t id = 0, + uint16_t offset = 0, + int64_t default_integer = 0, + double default_real = 0.0, + bool deprecated = false, + bool required = false, + bool key = false, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0, + bool optional = false) { + FieldBuilder builder_(_fbb); + builder_.add_default_real(default_real); + builder_.add_default_integer(default_integer); + builder_.add_documentation(documentation); + builder_.add_attributes(attributes); + builder_.add_type(type); + builder_.add_name(name); + builder_.add_offset(offset); + builder_.add_id(id); + builder_.add_optional(optional); + builder_.add_key(key); + builder_.add_required(required); + builder_.add_deprecated(deprecated); + return builder_.Finish(); +} + +inline flatbuffers::Offset<Field> CreateFieldDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *name = nullptr, + flatbuffers::Offset<reflection::Type> type = 0, + uint16_t id = 0, + uint16_t offset = 0, + int64_t default_integer = 0, + double default_real = 0.0, + bool deprecated = false, + bool required = false, + bool key = false, + std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr, + const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr, + bool optional = false) { + auto name__ = name ? _fbb.CreateString(name) : 0; + auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0; + auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; + return reflection::CreateField( + _fbb, + name__, + type, + id, + offset, + default_integer, + default_real, + deprecated, + required, + key, + attributes__, + documentation__, + optional); +} + +struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ObjectBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NAME = 4, + VT_FIELDS = 6, + VT_IS_STRUCT = 8, + VT_MINALIGN = 10, + VT_BYTESIZE = 12, + VT_ATTRIBUTES = 14, + VT_DOCUMENTATION = 16 + }; + const flatbuffers::String *name() const { + return GetPointer<const flatbuffers::String *>(VT_NAME); + } + bool KeyCompareLessThan(const Object *o) const { + return *name() < *o->name(); + } + int KeyCompareWithValue(const char *val) const { + return strcmp(name()->c_str(), val); + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *fields() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *>(VT_FIELDS); + } + bool is_struct() const { + return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0; + } + int32_t minalign() const { + return GetField<int32_t>(VT_MINALIGN, 0); + } + int32_t bytesize() const { + return GetField<int32_t>(VT_BYTESIZE, 0); + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES); + } + const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffsetRequired(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyOffsetRequired(verifier, VT_FIELDS) && + verifier.VerifyVector(fields()) && + verifier.VerifyVectorOfTables(fields()) && + VerifyField<uint8_t>(verifier, VT_IS_STRUCT) && + VerifyField<int32_t>(verifier, VT_MINALIGN) && + VerifyField<int32_t>(verifier, VT_BYTESIZE) && + VerifyOffset(verifier, VT_ATTRIBUTES) && + verifier.VerifyVector(attributes()) && + verifier.VerifyVectorOfTables(attributes()) && + VerifyOffset(verifier, VT_DOCUMENTATION) && + verifier.VerifyVector(documentation()) && + verifier.VerifyVectorOfStrings(documentation()) && + verifier.EndTable(); + } +}; + +struct ObjectBuilder { + typedef Object Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_name(flatbuffers::Offset<flatbuffers::String> name) { + fbb_.AddOffset(Object::VT_NAME, name); + } + void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Field>>> fields) { + fbb_.AddOffset(Object::VT_FIELDS, fields); + } + void add_is_struct(bool is_struct) { + fbb_.AddElement<uint8_t>(Object::VT_IS_STRUCT, static_cast<uint8_t>(is_struct), 0); + } + void add_minalign(int32_t minalign) { + fbb_.AddElement<int32_t>(Object::VT_MINALIGN, minalign, 0); + } + void add_bytesize(int32_t bytesize) { + fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0); + } + void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) { + fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes); + } + void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { + fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation); + } + explicit ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<Object> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<Object>(end); + fbb_.Required(o, Object::VT_NAME); + fbb_.Required(o, Object::VT_FIELDS); + return o; + } +}; + +inline flatbuffers::Offset<Object> CreateObject( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::String> name = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Field>>> fields = 0, + bool is_struct = false, + int32_t minalign = 0, + int32_t bytesize = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) { + ObjectBuilder builder_(_fbb); + builder_.add_documentation(documentation); + builder_.add_attributes(attributes); + builder_.add_bytesize(bytesize); + builder_.add_minalign(minalign); + builder_.add_fields(fields); + builder_.add_name(name); + builder_.add_is_struct(is_struct); + return builder_.Finish(); +} + +inline flatbuffers::Offset<Object> CreateObjectDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *name = nullptr, + std::vector<flatbuffers::Offset<reflection::Field>> *fields = nullptr, + bool is_struct = false, + int32_t minalign = 0, + int32_t bytesize = 0, + std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr, + const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { + auto name__ = name ? _fbb.CreateString(name) : 0; + auto fields__ = fields ? _fbb.CreateVectorOfSortedTables<reflection::Field>(fields) : 0; + auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0; + auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; + return reflection::CreateObject( + _fbb, + name__, + fields__, + is_struct, + minalign, + bytesize, + attributes__, + documentation__); +} + +struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef RPCCallBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NAME = 4, + VT_REQUEST = 6, + VT_RESPONSE = 8, + VT_ATTRIBUTES = 10, + VT_DOCUMENTATION = 12 + }; + const flatbuffers::String *name() const { + return GetPointer<const flatbuffers::String *>(VT_NAME); + } + bool KeyCompareLessThan(const RPCCall *o) const { + return *name() < *o->name(); + } + int KeyCompareWithValue(const char *val) const { + return strcmp(name()->c_str(), val); + } + const reflection::Object *request() const { + return GetPointer<const reflection::Object *>(VT_REQUEST); + } + const reflection::Object *response() const { + return GetPointer<const reflection::Object *>(VT_RESPONSE); + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES); + } + const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffsetRequired(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyOffsetRequired(verifier, VT_REQUEST) && + verifier.VerifyTable(request()) && + VerifyOffsetRequired(verifier, VT_RESPONSE) && + verifier.VerifyTable(response()) && + VerifyOffset(verifier, VT_ATTRIBUTES) && + verifier.VerifyVector(attributes()) && + verifier.VerifyVectorOfTables(attributes()) && + VerifyOffset(verifier, VT_DOCUMENTATION) && + verifier.VerifyVector(documentation()) && + verifier.VerifyVectorOfStrings(documentation()) && + verifier.EndTable(); + } +}; + +struct RPCCallBuilder { + typedef RPCCall Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_name(flatbuffers::Offset<flatbuffers::String> name) { + fbb_.AddOffset(RPCCall::VT_NAME, name); + } + void add_request(flatbuffers::Offset<reflection::Object> request) { + fbb_.AddOffset(RPCCall::VT_REQUEST, request); + } + void add_response(flatbuffers::Offset<reflection::Object> response) { + fbb_.AddOffset(RPCCall::VT_RESPONSE, response); + } + void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) { + fbb_.AddOffset(RPCCall::VT_ATTRIBUTES, attributes); + } + void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { + fbb_.AddOffset(RPCCall::VT_DOCUMENTATION, documentation); + } + explicit RPCCallBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<RPCCall> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<RPCCall>(end); + fbb_.Required(o, RPCCall::VT_NAME); + fbb_.Required(o, RPCCall::VT_REQUEST); + fbb_.Required(o, RPCCall::VT_RESPONSE); + return o; + } +}; + +inline flatbuffers::Offset<RPCCall> CreateRPCCall( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::String> name = 0, + flatbuffers::Offset<reflection::Object> request = 0, + flatbuffers::Offset<reflection::Object> response = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) { + RPCCallBuilder builder_(_fbb); + builder_.add_documentation(documentation); + builder_.add_attributes(attributes); + builder_.add_response(response); + builder_.add_request(request); + builder_.add_name(name); + return builder_.Finish(); +} + +inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *name = nullptr, + flatbuffers::Offset<reflection::Object> request = 0, + flatbuffers::Offset<reflection::Object> response = 0, + std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr, + const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { + auto name__ = name ? _fbb.CreateString(name) : 0; + auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0; + auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; + return reflection::CreateRPCCall( + _fbb, + name__, + request, + response, + attributes__, + documentation__); +} + +struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ServiceBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NAME = 4, + VT_CALLS = 6, + VT_ATTRIBUTES = 8, + VT_DOCUMENTATION = 10 + }; + const flatbuffers::String *name() const { + return GetPointer<const flatbuffers::String *>(VT_NAME); + } + bool KeyCompareLessThan(const Service *o) const { + return *name() < *o->name(); + } + int KeyCompareWithValue(const char *val) const { + return strcmp(name()->c_str(), val); + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *calls() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *>(VT_CALLS); + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES); + } + const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffsetRequired(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyOffset(verifier, VT_CALLS) && + verifier.VerifyVector(calls()) && + verifier.VerifyVectorOfTables(calls()) && + VerifyOffset(verifier, VT_ATTRIBUTES) && + verifier.VerifyVector(attributes()) && + verifier.VerifyVectorOfTables(attributes()) && + VerifyOffset(verifier, VT_DOCUMENTATION) && + verifier.VerifyVector(documentation()) && + verifier.VerifyVectorOfStrings(documentation()) && + verifier.EndTable(); + } +}; + +struct ServiceBuilder { + typedef Service Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_name(flatbuffers::Offset<flatbuffers::String> name) { + fbb_.AddOffset(Service::VT_NAME, name); + } + void add_calls(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls) { + fbb_.AddOffset(Service::VT_CALLS, calls); + } + void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) { + fbb_.AddOffset(Service::VT_ATTRIBUTES, attributes); + } + void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { + fbb_.AddOffset(Service::VT_DOCUMENTATION, documentation); + } + explicit ServiceBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<Service> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<Service>(end); + fbb_.Required(o, Service::VT_NAME); + return o; + } +}; + +inline flatbuffers::Offset<Service> CreateService( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::String> name = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) { + ServiceBuilder builder_(_fbb); + builder_.add_documentation(documentation); + builder_.add_attributes(attributes); + builder_.add_calls(calls); + builder_.add_name(name); + return builder_.Finish(); +} + +inline flatbuffers::Offset<Service> CreateServiceDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *name = nullptr, + std::vector<flatbuffers::Offset<reflection::RPCCall>> *calls = nullptr, + std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr, + const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { + auto name__ = name ? _fbb.CreateString(name) : 0; + auto calls__ = calls ? _fbb.CreateVectorOfSortedTables<reflection::RPCCall>(calls) : 0; + auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0; + auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; + return reflection::CreateService( + _fbb, + name__, + calls__, + attributes__, + documentation__); +} + +struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SchemaBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_OBJECTS = 4, + VT_ENUMS = 6, + VT_FILE_IDENT = 8, + VT_FILE_EXT = 10, + VT_ROOT_TABLE = 12, + VT_SERVICES = 14, + VT_ADVANCED_FEATURES = 16 + }; + const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *>(VT_OBJECTS); + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *>(VT_ENUMS); + } + const flatbuffers::String *file_ident() const { + return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT); + } + const flatbuffers::String *file_ext() const { + return GetPointer<const flatbuffers::String *>(VT_FILE_EXT); + } + const reflection::Object *root_table() const { + return GetPointer<const reflection::Object *>(VT_ROOT_TABLE); + } + const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *services() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *>(VT_SERVICES); + } + reflection::AdvancedFeatures advanced_features() const { + return static_cast<reflection::AdvancedFeatures>(GetField<uint64_t>(VT_ADVANCED_FEATURES, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffsetRequired(verifier, VT_OBJECTS) && + verifier.VerifyVector(objects()) && + verifier.VerifyVectorOfTables(objects()) && + VerifyOffsetRequired(verifier, VT_ENUMS) && + verifier.VerifyVector(enums()) && + verifier.VerifyVectorOfTables(enums()) && + VerifyOffset(verifier, VT_FILE_IDENT) && + verifier.VerifyString(file_ident()) && + VerifyOffset(verifier, VT_FILE_EXT) && + verifier.VerifyString(file_ext()) && + VerifyOffset(verifier, VT_ROOT_TABLE) && + verifier.VerifyTable(root_table()) && + VerifyOffset(verifier, VT_SERVICES) && + verifier.VerifyVector(services()) && + verifier.VerifyVectorOfTables(services()) && + VerifyField<uint64_t>(verifier, VT_ADVANCED_FEATURES) && + verifier.EndTable(); + } +}; + +struct SchemaBuilder { + typedef Schema Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>> objects) { + fbb_.AddOffset(Schema::VT_OBJECTS, objects); + } + void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums) { + fbb_.AddOffset(Schema::VT_ENUMS, enums); + } + void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) { + fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident); + } + void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) { + fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext); + } + void add_root_table(flatbuffers::Offset<reflection::Object> root_table) { + fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table); + } + void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services) { + fbb_.AddOffset(Schema::VT_SERVICES, services); + } + void add_advanced_features(reflection::AdvancedFeatures advanced_features) { + fbb_.AddElement<uint64_t>(Schema::VT_ADVANCED_FEATURES, static_cast<uint64_t>(advanced_features), 0); + } + explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<Schema> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<Schema>(end); + fbb_.Required(o, Schema::VT_OBJECTS); + fbb_.Required(o, Schema::VT_ENUMS); + return o; + } +}; + +inline flatbuffers::Offset<Schema> CreateSchema( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>> objects = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums = 0, + flatbuffers::Offset<flatbuffers::String> file_ident = 0, + flatbuffers::Offset<flatbuffers::String> file_ext = 0, + flatbuffers::Offset<reflection::Object> root_table = 0, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services = 0, + reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0)) { + SchemaBuilder builder_(_fbb); + builder_.add_advanced_features(advanced_features); + builder_.add_services(services); + builder_.add_root_table(root_table); + builder_.add_file_ext(file_ext); + builder_.add_file_ident(file_ident); + builder_.add_enums(enums); + builder_.add_objects(objects); + return builder_.Finish(); +} + +inline flatbuffers::Offset<Schema> CreateSchemaDirect( + flatbuffers::FlatBufferBuilder &_fbb, + std::vector<flatbuffers::Offset<reflection::Object>> *objects = nullptr, + std::vector<flatbuffers::Offset<reflection::Enum>> *enums = nullptr, + const char *file_ident = nullptr, + const char *file_ext = nullptr, + flatbuffers::Offset<reflection::Object> root_table = 0, + std::vector<flatbuffers::Offset<reflection::Service>> *services = nullptr, + reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0)) { + auto objects__ = objects ? _fbb.CreateVectorOfSortedTables<reflection::Object>(objects) : 0; + auto enums__ = enums ? _fbb.CreateVectorOfSortedTables<reflection::Enum>(enums) : 0; + auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0; + auto file_ext__ = file_ext ? _fbb.CreateString(file_ext) : 0; + auto services__ = services ? _fbb.CreateVectorOfSortedTables<reflection::Service>(services) : 0; + return reflection::CreateSchema( + _fbb, + objects__, + enums__, + file_ident__, + file_ext__, + root_table, + services__, + advanced_features); +} + +inline const reflection::Schema *GetSchema(const void *buf) { + return flatbuffers::GetRoot<reflection::Schema>(buf); +} + +inline const reflection::Schema *GetSizePrefixedSchema(const void *buf) { + return flatbuffers::GetSizePrefixedRoot<reflection::Schema>(buf); +} + +inline const char *SchemaIdentifier() { + return "BFBS"; +} + +inline bool SchemaBufferHasIdentifier(const void *buf) { + return flatbuffers::BufferHasIdentifier( + buf, SchemaIdentifier()); +} + +inline bool VerifySchemaBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier()); +} + +inline bool VerifySizePrefixedSchemaBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer<reflection::Schema>(SchemaIdentifier()); +} + +inline const char *SchemaExtension() { + return "bfbs"; +} + +inline void FinishSchemaBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset<reflection::Schema> root) { + fbb.Finish(root, SchemaIdentifier()); +} + +inline void FinishSizePrefixedSchemaBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset<reflection::Schema> root) { + fbb.FinishSizePrefixed(root, SchemaIdentifier()); +} + +} // namespace reflection + +#endif // FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_ diff --git a/contrib/libs/flatbuffers/include/flatbuffers/util.h b/contrib/libs/flatbuffers/include/flatbuffers/util.h new file mode 100644 index 0000000000..4493c561c2 --- /dev/null +++ b/contrib/libs/flatbuffers/include/flatbuffers/util.h @@ -0,0 +1,698 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_UTIL_H_ +#define FLATBUFFERS_UTIL_H_ + +#include <errno.h> + +#include "base.h" +#include "stl_emulation.h" + +#ifndef FLATBUFFERS_PREFER_PRINTF +# include <sstream> +#else // FLATBUFFERS_PREFER_PRINTF +# include <float.h> +# include <stdio.h> +#endif // FLATBUFFERS_PREFER_PRINTF + +#include <iomanip> +#include <string> + +namespace flatbuffers { + +// @locale-independent functions for ASCII characters set. + +// Fast checking that character lies in closed range: [a <= x <= b] +// using one compare (conditional branch) operator. +inline bool check_ascii_range(char x, char a, char b) { + FLATBUFFERS_ASSERT(a <= b); + // (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`. + // The x, a, b will be promoted to int and subtracted without overflow. + return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a); +} + +// Case-insensitive isalpha +inline bool is_alpha(char c) { + // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF). + return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF); +} + +// Check for uppercase alpha +inline bool is_alpha_upper(char c) { return check_ascii_range(c, 'A', 'Z'); } + +// Check (case-insensitive) that `c` is equal to alpha. +inline bool is_alpha_char(char c, char alpha) { + FLATBUFFERS_ASSERT(is_alpha(alpha)); + // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF). + return ((c & 0xDF) == (alpha & 0xDF)); +} + +// https://en.cppreference.com/w/cpp/string/byte/isxdigit +// isdigit and isxdigit are the only standard narrow character classification +// functions that are not affected by the currently installed C locale. although +// some implementations (e.g. Microsoft in 1252 codepage) may classify +// additional single-byte characters as digits. +inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); } + +inline bool is_xdigit(char c) { + // Replace by look-up table. + return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF); +} + +// Case-insensitive isalnum +inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); } + +inline char CharToUpper(char c) { + return static_cast<char>(::toupper(static_cast<unsigned char>(c))); +} + +inline char CharToLower(char c) { + return static_cast<char>(::tolower(static_cast<unsigned char>(c))); +} + +// @end-locale-independent functions for ASCII character set + +#ifdef FLATBUFFERS_PREFER_PRINTF +template<typename T> size_t IntToDigitCount(T t) { + size_t digit_count = 0; + // Count the sign for negative numbers + if (t < 0) digit_count++; + // Count a single 0 left of the dot for fractional numbers + if (-1 < t && t < 1) digit_count++; + // Count digits until fractional part + T eps = std::numeric_limits<float>::epsilon(); + while (t <= (-1 + eps) || (1 - eps) <= t) { + t /= 10; + digit_count++; + } + return digit_count; +} + +template<typename T> size_t NumToStringWidth(T t, int precision = 0) { + size_t string_width = IntToDigitCount(t); + // Count the dot for floating point numbers + if (precision) string_width += (precision + 1); + return string_width; +} + +template<typename T> +std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0) { + size_t string_width = NumToStringWidth(t, precision); + std::string s(string_width, 0x00); + // Allow snprintf to use std::string trailing null to detect buffer overflow + snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, string_width, t); + return s; +} +#endif // FLATBUFFERS_PREFER_PRINTF + +// Convert an integer or floating point value to a string. +// In contrast to std::stringstream, "char" values are +// converted to a string of digits, and we don't use scientific notation. +template<typename T> std::string NumToString(T t) { + // clang-format off + + #ifndef FLATBUFFERS_PREFER_PRINTF + std::stringstream ss; + ss << t; + return ss.str(); + #else // FLATBUFFERS_PREFER_PRINTF + auto v = static_cast<long long>(t); + return NumToStringImplWrapper(v, "%.*lld"); + #endif // FLATBUFFERS_PREFER_PRINTF + // clang-format on +} +// Avoid char types used as character data. +template<> inline std::string NumToString<signed char>(signed char t) { + return NumToString(static_cast<int>(t)); +} +template<> inline std::string NumToString<unsigned char>(unsigned char t) { + return NumToString(static_cast<int>(t)); +} +template<> inline std::string NumToString<char>(char t) { + return NumToString(static_cast<int>(t)); +} +#if defined(FLATBUFFERS_CPP98_STL) +template<> inline std::string NumToString<long long>(long long t) { + char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2 + snprintf(buf, sizeof(buf), "%lld", t); + return std::string(buf); +} + +template<> +inline std::string NumToString<unsigned long long>(unsigned long long t) { + char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1 + snprintf(buf, sizeof(buf), "%llu", t); + return std::string(buf); +} +#endif // defined(FLATBUFFERS_CPP98_STL) + +// Special versions for floats/doubles. +template<typename T> std::string FloatToString(T t, int precision) { + // clang-format off + + #ifndef FLATBUFFERS_PREFER_PRINTF + // to_string() prints different numbers of digits for floats depending on + // platform and isn't available on Android, so we use stringstream + std::stringstream ss; + // Use std::fixed to suppress scientific notation. + ss << std::fixed; + // Default precision is 6, we want that to be higher for doubles. + ss << std::setprecision(precision); + ss << t; + auto s = ss.str(); + #else // FLATBUFFERS_PREFER_PRINTF + auto v = static_cast<double>(t); + auto s = NumToStringImplWrapper(v, "%0.*f", precision); + #endif // FLATBUFFERS_PREFER_PRINTF + // clang-format on + // Sadly, std::fixed turns "1" into "1.00000", so here we undo that. + auto p = s.find_last_not_of('0'); + if (p != std::string::npos) { + // Strip trailing zeroes. If it is a whole number, keep one zero. + s.resize(p + (s[p] == '.' ? 2 : 1)); + } + return s; +} + +template<> inline std::string NumToString<double>(double t) { + return FloatToString(t, 12); +} +template<> inline std::string NumToString<float>(float t) { + return FloatToString(t, 6); +} + +// Convert an integer value to a hexadecimal string. +// The returned string length is always xdigits long, prefixed by 0 digits. +// For example, IntToStringHex(0x23, 8) returns the string "00000023". +inline std::string IntToStringHex(int i, int xdigits) { + FLATBUFFERS_ASSERT(i >= 0); + // clang-format off + + #ifndef FLATBUFFERS_PREFER_PRINTF + std::stringstream ss; + ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase + << i; + return ss.str(); + #else // FLATBUFFERS_PREFER_PRINTF + return NumToStringImplWrapper(i, "%.*X", xdigits); + #endif // FLATBUFFERS_PREFER_PRINTF + // clang-format on +} + +// clang-format off +// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}. +#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0) + class ClassicLocale { + #ifdef _MSC_VER + typedef _locale_t locale_type; + #else + typedef locale_t locale_type; // POSIX.1-2008 locale_t type + #endif + ClassicLocale(); + ~ClassicLocale(); + locale_type locale_; + static ClassicLocale instance_; + public: + static locale_type Get() { return instance_.locale_; } + }; + + #ifdef _MSC_VER + #define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get()) + #define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get()) + #define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get()) + #define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get()) + #else + #define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get()) + #define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get()) + #define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get()) + #define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get()) + #endif +#else + #define __strtod_impl(s, pe) strtod(s, pe) + #define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe)) + #ifdef _MSC_VER + #define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b) + #define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b) + #else + #define __strtoull_impl(s, pe, b) strtoull(s, pe, b) + #define __strtoll_impl(s, pe, b) strtoll(s, pe, b) + #endif +#endif + +inline void strtoval_impl(int64_t *val, const char *str, char **endptr, + int base) { + *val = __strtoll_impl(str, endptr, base); +} + +inline void strtoval_impl(uint64_t *val, const char *str, char **endptr, + int base) { + *val = __strtoull_impl(str, endptr, base); +} + +inline void strtoval_impl(double *val, const char *str, char **endptr) { + *val = __strtod_impl(str, endptr); +} + +// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true. +__supress_ubsan__("float-cast-overflow") +inline void strtoval_impl(float *val, const char *str, char **endptr) { + *val = __strtof_impl(str, endptr); +} +#undef __strtoull_impl +#undef __strtoll_impl +#undef __strtod_impl +#undef __strtof_impl +// clang-format on + +// Adaptor for strtoull()/strtoll(). +// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9), +// while strtoll with base=0 interprets first leading zero as octal prefix. +// In future, it is possible to add prefixed 0b0101. +// 1) Checks errno code for overflow condition (out of range). +// 2) If base <= 0, function try to detect base of number by prefix. +// +// Return value (like strtoull and strtoll, but reject partial result): +// - If successful, an integer value corresponding to the str is returned. +// - If full string conversion can't be performed, 0 is returned. +// - If the converted value falls out of range of corresponding return type, a +// range error occurs. In this case value MAX(T)/MIN(T) is returned. +template<typename T> +inline bool StringToIntegerImpl(T *val, const char *const str, + const int base = 0, + const bool check_errno = true) { + // T is int64_t or uint64_T + FLATBUFFERS_ASSERT(str); + if (base <= 0) { + auto s = str; + while (*s && !is_digit(*s)) s++; + if (s[0] == '0' && is_alpha_char(s[1], 'X')) + return StringToIntegerImpl(val, str, 16, check_errno); + // if a prefix not match, try base=10 + return StringToIntegerImpl(val, str, 10, check_errno); + } else { + if (check_errno) errno = 0; // clear thread-local errno + auto endptr = str; + strtoval_impl(val, str, const_cast<char **>(&endptr), base); + if ((*endptr != '\0') || (endptr == str)) { + *val = 0; // erase partial result + return false; // invalid string + } + // errno is out-of-range, return MAX/MIN + if (check_errno && errno) return false; + return true; + } +} + +template<typename T> +inline bool StringToFloatImpl(T *val, const char *const str) { + // Type T must be either float or double. + FLATBUFFERS_ASSERT(str && val); + auto end = str; + strtoval_impl(val, str, const_cast<char **>(&end)); + auto done = (end != str) && (*end == '\0'); + if (!done) *val = 0; // erase partial result + return done; +} + +// Convert a string to an instance of T. +// Return value (matched with StringToInteger64Impl and strtod): +// - If successful, a numeric value corresponding to the str is returned. +// - If full string conversion can't be performed, 0 is returned. +// - If the converted value falls out of range of corresponding return type, a +// range error occurs. In this case value MAX(T)/MIN(T) is returned. +template<typename T> inline bool StringToNumber(const char *s, T *val) { + // Assert on `unsigned long` and `signed long` on LP64. + // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>. + static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T"); + FLATBUFFERS_ASSERT(s && val); + int64_t i64; + // The errno check isn't needed, will return MAX/MIN on overflow. + if (StringToIntegerImpl(&i64, s, 0, false)) { + const int64_t max = (flatbuffers::numeric_limits<T>::max)(); + const int64_t min = flatbuffers::numeric_limits<T>::lowest(); + if (i64 > max) { + *val = static_cast<T>(max); + return false; + } + if (i64 < min) { + // For unsigned types return max to distinguish from + // "no conversion can be performed" when 0 is returned. + *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min); + return false; + } + *val = static_cast<T>(i64); + return true; + } + *val = 0; + return false; +} + +template<> inline bool StringToNumber<int64_t>(const char *str, int64_t *val) { + return StringToIntegerImpl(val, str); +} + +template<> +inline bool StringToNumber<uint64_t>(const char *str, uint64_t *val) { + if (!StringToIntegerImpl(val, str)) return false; + // The strtoull accepts negative numbers: + // If the minus sign was part of the input sequence, the numeric value + // calculated from the sequence of digits is negated as if by unary minus + // in the result type, which applies unsigned integer wraparound rules. + // Fix this behaviour (except -0). + if (*val) { + auto s = str; + while (*s && !is_digit(*s)) s++; + s = (s > str) ? (s - 1) : s; // step back to one symbol + if (*s == '-') { + // For unsigned types return the max to distinguish from + // "no conversion can be performed". + *val = (flatbuffers::numeric_limits<uint64_t>::max)(); + return false; + } + } + return true; +} + +template<> inline bool StringToNumber(const char *s, float *val) { + return StringToFloatImpl(val, s); +} + +template<> inline bool StringToNumber(const char *s, double *val) { + return StringToFloatImpl(val, s); +} + +inline int64_t StringToInt(const char *s, int base = 10) { + int64_t val; + return StringToIntegerImpl(&val, s, base) ? val : 0; +} + +inline uint64_t StringToUInt(const char *s, int base = 10) { + uint64_t val; + return StringToIntegerImpl(&val, s, base) ? val : 0; +} + +typedef bool (*LoadFileFunction)(const char *filename, bool binary, + std::string *dest); +typedef bool (*FileExistsFunction)(const char *filename); + +LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function); + +FileExistsFunction SetFileExistsFunction( + FileExistsFunction file_exists_function); + +// Check if file "name" exists. +bool FileExists(const char *name); + +// Check if "name" exists and it is also a directory. +bool DirExists(const char *name); + +// Load file "name" into "buf" returning true if successful +// false otherwise. If "binary" is false data is read +// using ifstream's text mode, otherwise data is read with +// no transcoding. +bool LoadFile(const char *name, bool binary, std::string *buf); + +// Save data "buf" of length "len" bytes into a file +// "name" returning true if successful, false otherwise. +// If "binary" is false data is written using ifstream's +// text mode, otherwise data is written with no +// transcoding. +bool SaveFile(const char *name, const char *buf, size_t len, bool binary); + +// Save data "buf" into file "name" returning true if +// successful, false otherwise. If "binary" is false +// data is written using ifstream's text mode, otherwise +// data is written with no transcoding. +inline bool SaveFile(const char *name, const std::string &buf, bool binary) { + return SaveFile(name, buf.c_str(), buf.size(), binary); +} + +// Functionality for minimalistic portable path handling. + +// The functions below behave correctly regardless of whether posix ('/') or +// Windows ('/' or '\\') separators are used. + +// Any new separators inserted are always posix. +FLATBUFFERS_CONSTEXPR char kPathSeparator = '/'; + +// Returns the path with the extension, if any, removed. +std::string StripExtension(const std::string &filepath); + +// Returns the extension, if any. +std::string GetExtension(const std::string &filepath); + +// Return the last component of the path, after the last separator. +std::string StripPath(const std::string &filepath); + +// Strip the last component of the path + separator. +std::string StripFileName(const std::string &filepath); + +// Concatenates a path with a filename, regardless of whether the path +// ends in a separator or not. +std::string ConCatPathFileName(const std::string &path, + const std::string &filename); + +// Replaces any '\\' separators with '/' +std::string PosixPath(const char *path); + +// This function ensure a directory exists, by recursively +// creating dirs for any parts of the path that don't exist yet. +void EnsureDirExists(const std::string &filepath); + +// Obtains the absolute path from any other path. +// Returns the input path if the absolute path couldn't be resolved. +std::string AbsolutePath(const std::string &filepath); + +// To and from UTF-8 unicode conversion functions + +// Convert a unicode code point into a UTF-8 representation by appending it +// to a string. Returns the number of bytes generated. +inline int ToUTF8(uint32_t ucc, std::string *out) { + FLATBUFFERS_ASSERT(!(ucc & 0x80000000)); // Top bit can't be set. + // 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8 + for (int i = 0; i < 6; i++) { + // Max bits this encoding can represent. + uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i); + if (ucc < (1u << max_bits)) { // does it fit? + // Remaining bits not encoded in the first byte, store 6 bits each + uint32_t remain_bits = i * 6; + // Store first byte: + (*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) | + (ucc >> remain_bits)); + // Store remaining bytes: + for (int j = i - 1; j >= 0; j--) { + (*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80); + } + return i + 1; // Return the number of bytes added. + } + } + FLATBUFFERS_ASSERT(0); // Impossible to arrive here. + return -1; +} + +// Converts whatever prefix of the incoming string corresponds to a valid +// UTF-8 sequence into a unicode code. The incoming pointer will have been +// advanced past all bytes parsed. +// returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in +// this case). +inline int FromUTF8(const char **in) { + int len = 0; + // Count leading 1 bits. + for (int mask = 0x80; mask >= 0x04; mask >>= 1) { + if (**in & mask) { + len++; + } else { + break; + } + } + if ((static_cast<unsigned char>(**in) << len) & 0x80) + return -1; // Bit after leading 1's must be 0. + if (!len) return *(*in)++; + // UTF-8 encoded values with a length are between 2 and 4 bytes. + if (len < 2 || len > 4) { return -1; } + // Grab initial bits of the code. + int ucc = *(*in)++ & ((1 << (7 - len)) - 1); + for (int i = 0; i < len - 1; i++) { + if ((**in & 0xC0) != 0x80) return -1; // Upper bits must 1 0. + ucc <<= 6; + ucc |= *(*in)++ & 0x3F; // Grab 6 more bits of the code. + } + // UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for + // UTF-16 surrogate pairs). + if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; } + // UTF-8 must represent code points in their shortest possible encoding. + switch (len) { + case 2: + // Two bytes of UTF-8 can represent code points from U+0080 to U+07FF. + if (ucc < 0x0080 || ucc > 0x07FF) { return -1; } + break; + case 3: + // Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF. + if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; } + break; + case 4: + // Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF. + if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; } + break; + } + return ucc; +} + +#ifndef FLATBUFFERS_PREFER_PRINTF +// Wraps a string to a maximum length, inserting new lines where necessary. Any +// existing whitespace will be collapsed down to a single space. A prefix or +// suffix can be provided, which will be inserted before or after a wrapped +// line, respectively. +inline std::string WordWrap(const std::string in, size_t max_length, + const std::string wrapped_line_prefix, + const std::string wrapped_line_suffix) { + std::istringstream in_stream(in); + std::string wrapped, line, word; + + in_stream >> word; + line = word; + + while (in_stream >> word) { + if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) < + max_length) { + line += " " + word; + } else { + wrapped += line + wrapped_line_suffix + "\n"; + line = wrapped_line_prefix + word; + } + } + wrapped += line; + + return wrapped; +} +#endif // !FLATBUFFERS_PREFER_PRINTF + +inline bool EscapeString(const char *s, size_t length, std::string *_text, + bool allow_non_utf8, bool natural_utf8) { + std::string &text = *_text; + text += "\""; + for (uoffset_t i = 0; i < length; i++) { + char c = s[i]; + switch (c) { + case '\n': text += "\\n"; break; + case '\t': text += "\\t"; break; + case '\r': text += "\\r"; break; + case '\b': text += "\\b"; break; + case '\f': text += "\\f"; break; + case '\"': text += "\\\""; break; + case '\\': text += "\\\\"; break; + default: + if (c >= ' ' && c <= '~') { + text += c; + } else { + // Not printable ASCII data. Let's see if it's valid UTF-8 first: + const char *utf8 = s + i; + int ucc = FromUTF8(&utf8); + if (ucc < 0) { + if (allow_non_utf8) { + text += "\\x"; + text += IntToStringHex(static_cast<uint8_t>(c), 2); + } else { + // There are two cases here: + // + // 1) We reached here by parsing an IDL file. In that case, + // we previously checked for non-UTF-8, so we shouldn't reach + // here. + // + // 2) We reached here by someone calling GenerateText() + // on a previously-serialized flatbuffer. The data might have + // non-UTF-8 Strings, or might be corrupt. + // + // In both cases, we have to give up and inform the caller + // they have no JSON. + return false; + } + } else { + if (natural_utf8) { + // utf8 points to past all utf-8 bytes parsed + text.append(s + i, static_cast<size_t>(utf8 - s - i)); + } else if (ucc <= 0xFFFF) { + // Parses as Unicode within JSON's \uXXXX range, so use that. + text += "\\u"; + text += IntToStringHex(ucc, 4); + } else if (ucc <= 0x10FFFF) { + // Encode Unicode SMP values to a surrogate pair using two \u + // escapes. + uint32_t base = ucc - 0x10000; + auto high_surrogate = (base >> 10) + 0xD800; + auto low_surrogate = (base & 0x03FF) + 0xDC00; + text += "\\u"; + text += IntToStringHex(high_surrogate, 4); + text += "\\u"; + text += IntToStringHex(low_surrogate, 4); + } + // Skip past characters recognized. + i = static_cast<uoffset_t>(utf8 - s - 1); + } + } + break; + } + } + text += "\""; + return true; +} + +inline std::string BufferToHexText(const void *buffer, size_t buffer_size, + size_t max_length, + const std::string &wrapped_line_prefix, + const std::string &wrapped_line_suffix) { + std::string text = wrapped_line_prefix; + size_t start_offset = 0; + const char *s = reinterpret_cast<const char *>(buffer); + for (size_t i = 0; s && i < buffer_size; i++) { + // Last iteration or do we have more? + bool have_more = i + 1 < buffer_size; + text += "0x"; + text += IntToStringHex(static_cast<uint8_t>(s[i]), 2); + if (have_more) { text += ','; } + // If we have more to process and we reached max_length + if (have_more && + text.size() + wrapped_line_suffix.size() >= start_offset + max_length) { + text += wrapped_line_suffix; + text += '\n'; + start_offset = text.size(); + text += wrapped_line_prefix; + } + } + text += wrapped_line_suffix; + return text; +} + +// Remove paired quotes in a string: "text"|'text' -> text. +std::string RemoveStringQuotes(const std::string &s); + +// Change th global C-locale to locale with name <locale_name>. +// Returns an actual locale name in <_value>, useful if locale_name is "" or +// null. +bool SetGlobalTestLocale(const char *locale_name, + std::string *_value = nullptr); + +// Read (or test) a value of environment variable. +bool ReadEnvironmentVariable(const char *var_name, + std::string *_value = nullptr); + +// MSVC specific: Send all assert reports to STDOUT to prevent CI hangs. +void SetupDefaultCRTReportMode(); + +} // namespace flatbuffers + +#endif // FLATBUFFERS_UTIL_H_ |