mirror of https://github.com/axmolengine/axmol.git
271 lines
10 KiB
C
271 lines
10 KiB
C
|
/*
|
||
|
* 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_H_
|
||
|
#define FLATBUFFERS_H_
|
||
|
|
||
|
// TODO: These includes are for mitigating the pains of users editing their
|
||
|
// source because they relied on flatbuffers.h to include everything for them.
|
||
|
#include "flatbuffers/array.h"
|
||
|
#include "flatbuffers/base.h"
|
||
|
#include "flatbuffers/buffer.h"
|
||
|
#include "flatbuffers/buffer_ref.h"
|
||
|
#include "flatbuffers/detached_buffer.h"
|
||
|
#include "flatbuffers/flatbuffer_builder.h"
|
||
|
#include "flatbuffers/stl_emulation.h"
|
||
|
#include "flatbuffers/string.h"
|
||
|
#include "flatbuffers/struct.h"
|
||
|
#include "flatbuffers/table.h"
|
||
|
#include "flatbuffers/vector.h"
|
||
|
#include "flatbuffers/vector_downward.h"
|
||
|
#include "flatbuffers/verifier.h"
|
||
|
|
||
|
namespace flatbuffers {
|
||
|
|
||
|
/// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
|
||
|
/// it is the opposite transformation of GetRoot().
|
||
|
/// This may be useful if you want to pass on a root and have the recipient
|
||
|
/// delete the buffer afterwards.
|
||
|
inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
|
||
|
auto table = reinterpret_cast<const Table *>(root);
|
||
|
auto vtable = table->GetVTable();
|
||
|
// Either the vtable is before the root or after the root.
|
||
|
auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
|
||
|
// Align to at least sizeof(uoffset_t).
|
||
|
start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
|
||
|
~(sizeof(uoffset_t) - 1));
|
||
|
// Additionally, there may be a file_identifier in the buffer, and the root
|
||
|
// offset. The buffer may have been aligned to any size between
|
||
|
// sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
|
||
|
// Sadly, the exact alignment is only known when constructing the buffer,
|
||
|
// since it depends on the presence of values with said alignment properties.
|
||
|
// So instead, we simply look at the next uoffset_t values (root,
|
||
|
// file_identifier, and alignment padding) to see which points to the root.
|
||
|
// None of the other values can "impersonate" the root since they will either
|
||
|
// be 0 or four ASCII characters.
|
||
|
static_assert(flatbuffers::kFileIdentifierLength == sizeof(uoffset_t),
|
||
|
"file_identifier is assumed to be the same size as uoffset_t");
|
||
|
for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
|
||
|
possible_roots; possible_roots--) {
|
||
|
start -= sizeof(uoffset_t);
|
||
|
if (ReadScalar<uoffset_t>(start) + start ==
|
||
|
reinterpret_cast<const uint8_t *>(root))
|
||
|
return start;
|
||
|
}
|
||
|
// We didn't find the root, either the "root" passed isn't really a root,
|
||
|
// or the buffer is corrupt.
|
||
|
// Assert, because calling this function with bad data may cause reads
|
||
|
// outside of buffer boundaries.
|
||
|
FLATBUFFERS_ASSERT(false);
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
/// @brief This return the prefixed size of a FlatBuffer.
|
||
|
inline uoffset_t GetPrefixedSize(const uint8_t *buf) {
|
||
|
return ReadScalar<uoffset_t>(buf);
|
||
|
}
|
||
|
|
||
|
// Base class for native objects (FlatBuffer data de-serialized into native
|
||
|
// C++ data structures).
|
||
|
// Contains no functionality, purely documentative.
|
||
|
struct NativeTable {};
|
||
|
|
||
|
/// @brief Function types to be used with resolving hashes into objects and
|
||
|
/// back again. The resolver gets a pointer to a field inside an object API
|
||
|
/// object that is of the type specified in the schema using the attribute
|
||
|
/// `cpp_type` (it is thus important whatever you write to this address
|
||
|
/// matches that type). The value of this field is initially null, so you
|
||
|
/// may choose to implement a delayed binding lookup using this function
|
||
|
/// if you wish. The resolver does the opposite lookup, for when the object
|
||
|
/// is being serialized again.
|
||
|
typedef uint64_t hash_value_t;
|
||
|
typedef std::function<void(void **pointer_adr, hash_value_t hash)>
|
||
|
resolver_function_t;
|
||
|
typedef std::function<hash_value_t(void *pointer)> rehasher_function_t;
|
||
|
|
||
|
// Helper function to test if a field is present, using any of the field
|
||
|
// enums in the generated code.
|
||
|
// `table` must be a generated table type. Since this is a template parameter,
|
||
|
// this is not typechecked to be a subclass of Table, so beware!
|
||
|
// Note: this function will return false for fields equal to the default
|
||
|
// value, since they're not stored in the buffer (unless force_defaults was
|
||
|
// used).
|
||
|
template<typename T>
|
||
|
bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) {
|
||
|
// Cast, since Table is a private baseclass of any table types.
|
||
|
return reinterpret_cast<const Table *>(table)->CheckField(
|
||
|
static_cast<voffset_t>(field));
|
||
|
}
|
||
|
|
||
|
// Utility function for reverse lookups on the EnumNames*() functions
|
||
|
// (in the generated C++ code)
|
||
|
// names must be NULL terminated.
|
||
|
inline int LookupEnum(const char **names, const char *name) {
|
||
|
for (const char **p = names; *p; p++)
|
||
|
if (!strcmp(*p, name)) return static_cast<int>(p - names);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// These macros allow us to layout a struct with a guarantee that they'll end
|
||
|
// up looking the same on different compilers and platforms.
|
||
|
// It does this by disallowing the compiler to do any padding, and then
|
||
|
// does padding itself by inserting extra padding fields that make every
|
||
|
// element aligned to its own size.
|
||
|
// Additionally, it manually sets the alignment of the struct as a whole,
|
||
|
// which is typically its largest element, or a custom size set in the schema
|
||
|
// by the force_align attribute.
|
||
|
// These are used in the generated code only.
|
||
|
|
||
|
// clang-format off
|
||
|
#if defined(_MSC_VER)
|
||
|
#define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
|
||
|
__pragma(pack(1)) \
|
||
|
struct __declspec(align(alignment))
|
||
|
#define FLATBUFFERS_STRUCT_END(name, size) \
|
||
|
__pragma(pack()) \
|
||
|
static_assert(sizeof(name) == size, "compiler breaks packing rules")
|
||
|
#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
|
||
|
#define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
|
||
|
_Pragma("pack(1)") \
|
||
|
struct __attribute__((aligned(alignment)))
|
||
|
#define FLATBUFFERS_STRUCT_END(name, size) \
|
||
|
_Pragma("pack()") \
|
||
|
static_assert(sizeof(name) == size, "compiler breaks packing rules")
|
||
|
#else
|
||
|
#error Unknown compiler, please define structure alignment macros
|
||
|
#endif
|
||
|
// clang-format on
|
||
|
|
||
|
// Minimal reflection via code generation.
|
||
|
// Besides full-fat reflection (see reflection.h) and parsing/printing by
|
||
|
// loading schemas (see idl.h), we can also have code generation for minimal
|
||
|
// reflection data which allows pretty-printing and other uses without needing
|
||
|
// a schema or a parser.
|
||
|
// Generate code with --reflect-types (types only) or --reflect-names (names
|
||
|
// also) to enable.
|
||
|
// See minireflect.h for utilities using this functionality.
|
||
|
|
||
|
// These types are organized slightly differently as the ones in idl.h.
|
||
|
enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
|
||
|
|
||
|
// Scalars have the same order as in idl.h
|
||
|
// clang-format off
|
||
|
#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
|
||
|
ET(ET_UTYPE) \
|
||
|
ET(ET_BOOL) \
|
||
|
ET(ET_CHAR) \
|
||
|
ET(ET_UCHAR) \
|
||
|
ET(ET_SHORT) \
|
||
|
ET(ET_USHORT) \
|
||
|
ET(ET_INT) \
|
||
|
ET(ET_UINT) \
|
||
|
ET(ET_LONG) \
|
||
|
ET(ET_ULONG) \
|
||
|
ET(ET_FLOAT) \
|
||
|
ET(ET_DOUBLE) \
|
||
|
ET(ET_STRING) \
|
||
|
ET(ET_SEQUENCE) // See SequenceType.
|
||
|
|
||
|
enum ElementaryType {
|
||
|
#define FLATBUFFERS_ET(E) E,
|
||
|
FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
|
||
|
#undef FLATBUFFERS_ET
|
||
|
};
|
||
|
|
||
|
inline const char * const *ElementaryTypeNames() {
|
||
|
static const char * const names[] = {
|
||
|
#define FLATBUFFERS_ET(E) #E,
|
||
|
FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
|
||
|
#undef FLATBUFFERS_ET
|
||
|
};
|
||
|
return names;
|
||
|
}
|
||
|
// clang-format on
|
||
|
|
||
|
// Basic type info cost just 16bits per field!
|
||
|
// We're explicitly defining the signedness since the signedness of integer
|
||
|
// bitfields is otherwise implementation-defined and causes warnings on older
|
||
|
// GCC compilers.
|
||
|
struct TypeCode {
|
||
|
// ElementaryType
|
||
|
unsigned short base_type : 4;
|
||
|
// Either vector (in table) or array (in struct)
|
||
|
unsigned short is_repeating : 1;
|
||
|
// Index into type_refs below, or -1 for none.
|
||
|
signed short sequence_ref : 11;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(TypeCode) == 2, "TypeCode");
|
||
|
|
||
|
struct TypeTable;
|
||
|
|
||
|
// Signature of the static method present in each type.
|
||
|
typedef const TypeTable *(*TypeFunction)();
|
||
|
|
||
|
struct TypeTable {
|
||
|
SequenceType st;
|
||
|
size_t num_elems; // of type_codes, values, names (but not type_refs).
|
||
|
const TypeCode *type_codes; // num_elems count
|
||
|
const TypeFunction *type_refs; // less than num_elems entries (see TypeCode).
|
||
|
const int16_t *array_sizes; // less than num_elems entries (see TypeCode).
|
||
|
const int64_t *values; // Only set for non-consecutive enum/union or structs.
|
||
|
const char *const *names; // Only set if compiled with --reflect-names.
|
||
|
};
|
||
|
|
||
|
// String which identifies the current version of FlatBuffers.
|
||
|
inline const char *flatbuffers_version_string() {
|
||
|
return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
|
||
|
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
|
||
|
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
|
||
|
}
|
||
|
|
||
|
// clang-format off
|
||
|
#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
|
||
|
inline E operator | (E lhs, E rhs){\
|
||
|
return E(T(lhs) | T(rhs));\
|
||
|
}\
|
||
|
inline E operator & (E lhs, E rhs){\
|
||
|
return E(T(lhs) & T(rhs));\
|
||
|
}\
|
||
|
inline E operator ^ (E lhs, E rhs){\
|
||
|
return E(T(lhs) ^ T(rhs));\
|
||
|
}\
|
||
|
inline E operator ~ (E lhs){\
|
||
|
return E(~T(lhs));\
|
||
|
}\
|
||
|
inline E operator |= (E &lhs, E rhs){\
|
||
|
lhs = lhs | rhs;\
|
||
|
return lhs;\
|
||
|
}\
|
||
|
inline E operator &= (E &lhs, E rhs){\
|
||
|
lhs = lhs & rhs;\
|
||
|
return lhs;\
|
||
|
}\
|
||
|
inline E operator ^= (E &lhs, E rhs){\
|
||
|
lhs = lhs ^ rhs;\
|
||
|
return lhs;\
|
||
|
}\
|
||
|
inline bool operator !(E rhs) \
|
||
|
{\
|
||
|
return !bool(T(rhs)); \
|
||
|
}
|
||
|
/// @endcond
|
||
|
} // namespace flatbuffers
|
||
|
|
||
|
// clang-format on
|
||
|
|
||
|
#endif // FLATBUFFERS_H_
|