diff options
author | Hyeongseok Oh <hseok82.oh@samsung.com> | 2023-09-08 10:51:25 +0000 |
---|---|---|
committer | Hyeongseok Oh <hseok82.oh@samsung.com> | 2023-09-08 10:51:25 +0000 |
commit | eed258505ee1ad0f72d9e0a8a3934f2e9e7b5e79 (patch) | |
tree | 1aa860656489469003375a0f67edb1d729f7dc6b /onert-micro/externals/flatbuffers/reflection.h | |
parent | 3a0ad354832744d138b361ffcfd21f33494beb6b (diff) | |
download | nnfw-upstream.tar.gz nnfw-upstream.tar.bz2 nnfw-upstream.zip |
Imported Upstream version 1.25.0upstream/1.25.0submit/tizen/20230908.105404upstream
Diffstat (limited to 'onert-micro/externals/flatbuffers/reflection.h')
-rw-r--r-- | onert-micro/externals/flatbuffers/reflection.h | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/onert-micro/externals/flatbuffers/reflection.h b/onert-micro/externals/flatbuffers/reflection.h new file mode 100644 index 000000000..8e2b155f7 --- /dev/null +++ b/onert-micro/externals/flatbuffers/reflection.h @@ -0,0 +1,520 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * 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 "flatbuffers/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_ |